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 *******************************************************************************/
33 #include "threads/thread.h"
36 /* global variables ***********************************************************/
38 extern bool newcompiler; /* true if new compiler is used */
40 int count_class_infos = 0; /* variables for measurements */
41 int count_const_pool_len = 0;
42 int count_vftbl_len = 0;
43 int count_all_methods = 0;
44 int count_vmcode_len = 0;
45 int count_extable_len = 0;
46 int count_class_loads = 0;
47 int count_class_inits = 0;
49 bool loadverbose = false; /* switches for debug messages */
50 bool linkverbose = false;
51 bool initverbose = false;
53 bool makeinitializations = true;
55 bool getloadingtime = false; /* to measure the runtime */
56 long int loadingtime = 0;
58 static s4 interfaceindex; /* sequential numbering of interfaces */
60 list unloadedclasses; /* list of all referenced but not loaded classes */
61 list unlinkedclasses; /* list of all loaded but not linked classes */
62 list linkedclasses; /* list of all completely linked classes */
65 /* utf-symbols for pointer comparison of frequently used strings */
67 static utf *utf_innerclasses; /* InnerClasses */
68 static utf *utf_constantvalue; /* ConstantValue */
69 static utf *utf_code; /* Code */
70 static utf *utf_finalize; /* finalize */
71 static utf *utf_fidesc; /* ()V */
72 static utf *utf_clinit; /* <clinit> */
73 static utf *utf_initsystemclass; /* initializeSystemClass */
74 static utf *utf_systemclass; /* java/lang/System */
77 /* important system classes ***************************************************/
79 classinfo *class_java_lang_Object;
80 classinfo *class_java_lang_String;
81 classinfo *class_java_lang_ClassCastException;
82 classinfo *class_java_lang_NullPointerException;
83 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
84 classinfo *class_java_lang_NegativeArraySizeException;
85 classinfo *class_java_lang_OutOfMemoryError;
86 classinfo *class_java_lang_ArithmeticException;
87 classinfo *class_java_lang_ArrayStoreException;
88 classinfo *class_java_lang_ThreadDeath;
89 classinfo *class_array = NULL;
92 /******************************************************************************
94 structure for primitive classes: contains the class for wrapping the
95 primitive type, the primitive class, the name of the class for wrapping,
96 the one character type signature and the name of the primitive class
98 ******************************************************************************/
100 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
101 { NULL, NULL, "java/lang/Double", 'D', "double" },
102 { NULL, NULL, "java/lang/Float", 'F', "float" },
103 { NULL, NULL, "java/lang/Character", 'C', "char" },
104 { NULL, NULL, "java/lang/Integer", 'I', "int" },
105 { NULL, NULL, "java/lang/Long", 'J', "long" },
106 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
107 { NULL, NULL, "java/lang/Short", 'S', "short" },
108 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
109 { NULL, NULL, "java/lang/Void", 'V', "void" }};
112 /* instances of important system classes **************************************/
114 java_objectheader *proto_java_lang_ClassCastException;
115 java_objectheader *proto_java_lang_NullPointerException;
116 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
117 java_objectheader *proto_java_lang_NegativeArraySizeException;
118 java_objectheader *proto_java_lang_OutOfMemoryError;
119 java_objectheader *proto_java_lang_ArithmeticException;
120 java_objectheader *proto_java_lang_ArrayStoreException;
121 java_objectheader *proto_java_lang_ThreadDeath;
124 /************* functions for reading classdata *********************************
126 getting classdata in blocks of variable size
127 (8,16,32,64-bit integer or float)
129 *******************************************************************************/
131 static char *classpath = ""; /* searchpath for classfiles */
132 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
133 static u1 *classbuf_pos; /* current position in classfile buffer */
134 static int classbuffer_size; /* size of classfile-data */
136 /* transfer block of classfile data into a buffer */
138 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
141 /* skip block of classfile data */
143 #define skip_nbytes(len) classbuf_pos+=len;
145 #define suck_u1() (*++classbuf_pos)
146 #define suck_s8() (s8) suck_u8()
147 #define suck_s2() (s2) suck_u2()
148 #define suck_s4() (s4) suck_u4()
149 #define suck_s1() (s1) suck_u1()
150 #define suck_u2() (u2) ((suck_u1()<<8)+suck_u1())
151 #define suck_u4() (u4) ((((u4)suck_u1())<<24)+(((u4)suck_u1())<<16)+(((u4)suck_u1())<<8)+((u4)suck_u1()))
154 /* get u8 from classfile data */
162 return (hi<<32) + lo;
171 /* get float from classfile data */
173 static float suck_float ()
180 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
181 memcpy ( (u1*) (&f), buffer, 4);
183 suck_nbytes ( (u1*) (&f), 4 );
186 PANICIF (sizeof(float) != 4, "Incompatible float-format");
191 /* get double from classfile data */
192 static double suck_double ()
199 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
200 memcpy ( (u1*) (&d), buffer, 8);
202 suck_nbytes ( (u1*) (&d), 8 );
205 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
210 /************************** function suck_init *********************************
212 called once at startup, sets the searchpath for the classfiles
214 *******************************************************************************/
216 void suck_init (char *cpath)
223 /************************** function suck_start ********************************
225 returns true if classbuffer is already loaded or a file for the
226 specified class has succussfully been read in. All directories of
227 the searchpath are used to find the classfile (<classname>.class).
228 Returns false if no classfile is found and writes an error message.
230 *******************************************************************************/
233 bool suck_start (utf *classname) {
235 #define MAXFILENAME 1000 /* maximum length of a filename */
237 char filename[MAXFILENAME+10]; /* room for '.class' */
238 char *pathpos; /* position in searchpath */
239 char c, *utf_ptr; /* pointer to the next utf8-character */
241 int filenamelen, err;
244 if (classbuffer) /* classbuffer is already valid */
251 /* skip path separator */
253 while (*pathpos == ':')
256 /* extract directory from searchpath */
259 while ((*pathpos) && (*pathpos!=':')) {
260 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
261 filename[filenamelen++] = *(pathpos++);
264 filename[filenamelen++] = '/';
266 /* add classname to filename */
268 utf_ptr = classname->text;
269 while (utf_ptr < utf_end(classname)) {
270 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
272 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
274 filename[filenamelen++] = c;
279 strcpy (filename+filenamelen, ".class");
281 classfile = fopen(filename, "r");
282 if (classfile) { /* file exists */
284 /* determine size of classfile */
286 err = stat (filename, &buffer);
288 if (!err) { /* read classfile data */
289 classbuffer_size = buffer.st_size;
290 classbuffer = MNEW(u1, classbuffer_size);
291 classbuf_pos = classbuffer-1;
292 fread(classbuffer, 1, classbuffer_size, classfile);
300 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
308 /************************** function suck_stop *********************************
310 frees memory for buffer with classfile data.
311 Caution: this function may only be called if buffer has been allocated
312 by suck_start with reading a file
314 *******************************************************************************/
318 /* determine amount of classdata not retrieved by suck-operations */
320 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
322 if (classdata_left > 0) {
324 sprintf (logtext,"There are %d access bytes at end of classfile",
331 MFREE(classbuffer, u1, classbuffer_size);
335 /******************************************************************************/
336 /******************* Einige Support-Funkionen *********************************/
337 /******************************************************************************/
340 /********** interne Funktion: printflags (nur zu Debug-Zwecken) **************/
342 static void printflags (u2 f)
344 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
345 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
346 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
347 if ( f & ACC_STATIC ) printf (" STATIC");
348 if ( f & ACC_FINAL ) printf (" FINAL");
349 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
350 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
351 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
352 if ( f & ACC_NATIVE ) printf (" NATIVE");
353 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
354 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
358 /************************* Funktion: skipattribute *****************************
360 "uberliest im ClassFile eine (1) 'attribute'-Struktur
362 *******************************************************************************/
364 static void skipattribute ()
367 skip_nbytes(suck_u4());
370 /********************** Funktion: skipattributebody ****************************
372 "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name -
373 Referenz schon gelesen worden ist.
375 *******************************************************************************/
377 static void skipattributebody ()
379 skip_nbytes(suck_u4());
382 /************************* Funktion: skipattributes ****************************
384 "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
386 *******************************************************************************/
388 static void skipattributes (u4 num)
391 for (i = 0; i < num; i++)
395 /******************** function: innerclass_getconstant ************************
397 like class_getconstant, but if cptags is ZERO null is returned
399 *******************************************************************************/
401 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
403 /* invalid position in constantpool */
404 if (pos >= c->cpcount)
405 panic ("Attempt to access constant outside range");
407 /* constantpool entry of type 0 */
411 /* check type of constantpool entry */
412 if (c->cptags[pos] != ctype) {
413 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
414 (int) ctype, (int) c->cptags[pos] );
418 return c->cpinfos[pos];
421 /************************ function: attribute_load ****************************
423 read attributes from classfile
425 *******************************************************************************/
427 static void attribute_load (u4 num, classinfo *c)
431 for (i = 0; i < num; i++) {
432 /* retrieve attribute name */
433 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
435 if ( aname == utf_innerclasses) {
436 /* innerclasses attribute */
438 /* skip attribute length */
440 /* number of records */
441 c->innerclasscount = suck_u2();
442 /* allocate memory for innerclass structure */
443 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
445 for (j=0;j<c->innerclasscount;j++) {
447 /* The innerclass structure contains a class with an encoded name,
448 its defining scope, its simple name and a bitmask of the access flags.
449 If an inner class is not a member, its outer_class is NULL,
450 if a class is anonymous, its name is NULL. */
452 innerclassinfo *info = c->innerclass + j;
454 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
455 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
456 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
457 info->flags = suck_u2 (); /* access_flags bitmask */
460 /* unknown attribute */
461 skipattributebody ();
466 /******************* function: checkfielddescriptor ****************************
468 checks whether a field-descriptor is valid and aborts otherwise
469 all referenced classes are inserted into the list of unloaded classes
471 *******************************************************************************/
473 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
475 char *tstart; /* pointer to start of classname */
478 switch (*utf_ptr++) {
491 /* save start of classname */
494 /* determine length of classname */
495 while ( *utf_ptr++ != ';' )
496 if (utf_ptr>=end_pos)
497 panic ("Missing ';' in objecttype-descriptor");
499 /* cause loading of referenced class */
500 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
505 while ((ch = *utf_ptr++)=='[')
508 /* component type of array */
522 /* save start of classname */
525 /* determine length of classname */
526 while ( *utf_ptr++ != ';' )
527 if (utf_ptr>=end_pos)
528 panic ("Missing ';' in objecttype-descriptor");
530 /* cause loading of referenced class */
531 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
535 panic ("Ill formed methodtype-descriptor");
540 panic ("Ill formed methodtype-descriptor");
543 /* exceeding characters */
544 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
548 /******************* function checkmethoddescriptor ****************************
550 checks whether a method-descriptor is valid and aborts otherwise.
551 All referenced classes are inserted into the list of unloaded classes.
553 *******************************************************************************/
555 static void checkmethoddescriptor (utf *d)
557 char *utf_ptr = d->text; /* current position in utf text */
558 char *end_pos = utf_end(d); /* points behind utf string */
559 char *tstart; /* pointer to start of classname */
562 /* method descriptor must start with parenthesis */
563 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
565 /* check arguments */
566 while ((c = *utf_ptr++) != ')') {
580 /* save start of classname */
583 /* determine length of classname */
584 while ( *utf_ptr++ != ';' )
585 if (utf_ptr>=end_pos)
586 panic ("Missing ';' in objecttype-descriptor");
588 /* cause loading of referenced class */
589 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
594 while ((ch = *utf_ptr++)=='[')
597 /* component type of array */
611 /* save start of classname */
614 /* determine length of classname */
615 while ( *utf_ptr++ != ';' )
616 if (utf_ptr>=end_pos)
617 panic ("Missing ';' in objecttype-descriptor");
619 /* cause loading of referenced class */
620 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
624 panic ("Ill formed methodtype-descriptor");
629 panic ("Ill formed methodtype-descriptor");
633 /* check returntype */
635 /* returntype void */
636 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
639 /* treat as field-descriptor */
640 checkfielddescriptor (utf_ptr,end_pos);
644 /******************** Funktion: buildarraydescriptor ***************************
646 erzeugt zu einem namentlich als utf-String vorliegenden Arraytyp eine
647 entsprechende constant_arraydescriptor - Struktur
649 *******************************************************************************/
651 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
653 constant_arraydescriptor *d;
655 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
657 d = NEW (constant_arraydescriptor);
658 d -> objectclass = NULL;
659 d -> elementdescriptor = NULL;
662 count_const_pool_len += sizeof(constant_arraydescriptor);
666 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
667 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
668 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
669 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
670 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
671 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
672 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
673 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
676 d -> arraytype = ARRAYTYPE_ARRAY;
677 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
681 d -> arraytype = ARRAYTYPE_OBJECT;
682 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
689 /******************* Funktion: freearraydescriptor *****************************
691 entfernt eine mit buildarraydescriptor erzeugte Struktur wieder
694 *******************************************************************************/
696 static void freearraydescriptor (constant_arraydescriptor *d)
699 constant_arraydescriptor *n = d->elementdescriptor;
700 FREE (d, constant_arraydescriptor);
705 /*********************** Funktion: displayarraydescriptor *********************/
707 static void displayarraydescriptor (constant_arraydescriptor *d)
709 switch (d->arraytype) {
710 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
711 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
712 case ARRAYTYPE_CHAR: printf ("char[]"); break;
713 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
714 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
715 case ARRAYTYPE_INT: printf ("int[]"); break;
716 case ARRAYTYPE_LONG: printf ("long[]"); break;
717 case ARRAYTYPE_SHORT: printf ("short[]"); break;
718 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
719 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
725 /******************************************************************************/
726 /******************** Funktionen fuer Fields **********************************/
727 /******************************************************************************/
730 /************************ Funktion: field_load *********************************
732 l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
733 und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
734 Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
737 *******************************************************************************/
739 static void field_load (fieldinfo *f, classinfo *c)
744 f -> flags = suck_u2 (); /* ACC flags */
745 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
746 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
747 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
748 f -> offset = 0; /* offset from start of object */
751 case TYPE_INT: f->value.i = 0; break;
752 case TYPE_FLOAT: f->value.f = 0.0; break;
753 case TYPE_DOUBLE: f->value.d = 0.0; break;
754 case TYPE_ADDRESS: f->value.a = NULL;
755 heap_addreference (&(f->value.a)); /* make global reference (GC) */
759 f->value.l = 0; break;
761 f->value.l.low = 0; f->value.l.high = 0; break;
765 /* read attributes */
767 for (i=0; i<attrnum; i++) {
771 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
773 if ( aname != utf_constantvalue ) {
774 /* unknown attribute */
775 skipattributebody ();
778 /* constant value attribute */
780 /* skip attribute length */
782 /* index of value in constantpool */
785 /* initialize field with value from constantpool */
788 constant_integer *ci =
789 class_getconstant(c, pindex, CONSTANT_Integer);
790 f->value.i = ci -> value;
796 class_getconstant(c, pindex, CONSTANT_Long);
798 f->value.l = cl -> value;
804 class_getconstant(c, pindex, CONSTANT_Float);
806 f->value.f = cf->value;
811 constant_double *cd =
812 class_getconstant(c, pindex, CONSTANT_Double);
814 f->value.d = cd->value;
819 utf *u = class_getconstant(c, pindex, CONSTANT_String);
820 /* create javastring from compressed utf8-string */
821 f->value.a = literalstring_new(u);
826 log_text ("Invalid Constant - Type");
835 /********************** function: field_free **********************************/
837 static void field_free (fieldinfo *f)
843 /************** Funktion: field_display (nur zu Debug-Zwecken) ****************/
845 static void field_display (fieldinfo *f)
848 printflags (f -> flags);
850 utf_display (f -> name);
852 utf_display (f -> descriptor);
853 printf (" offset: %ld\n", (long int) (f -> offset) );
857 /******************************************************************************/
858 /************************* Funktionen f"ur Methods ****************************/
859 /******************************************************************************/
862 /*********************** Funktion: method_load *********************************
864 l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit
865 eine schon existierende 'methodinfo'-Struktur aus.
866 Bei allen native-Methoden wird au"serdem gleich der richtige
867 Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
868 Zeiger auf den Compiler
870 *******************************************************************************/
872 static void method_load (methodinfo *m, classinfo *c)
882 m -> flags = suck_u2 ();
883 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
884 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
887 m -> exceptiontable = NULL;
888 m -> entrypoint = NULL;
890 m -> stubroutine = NULL;
892 if (! (m->flags & ACC_NATIVE) ) {
893 m -> stubroutine = createcompilerstub (m);
897 functionptr f = native_findfunction
898 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
903 m -> stubroutine = createnativestub (f, m);
906 m -> stubroutine = oldcreatenativestub (f, m);
913 for (i=0; i<attrnum; i++) {
916 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
918 if ( aname != utf_code) {
919 skipattributebody ();
922 if (m -> jcode) panic ("Two code-attributes for one method!");
925 m -> maxstack = suck_u2();
926 m -> maxlocals = suck_u2();
927 m -> jcodelength = suck_u4();
928 m -> jcode = MNEW (u1, m->jcodelength);
929 suck_nbytes (m->jcode, m->jcodelength);
930 m -> exceptiontablelength = suck_u2 ();
931 m -> exceptiontable =
932 MNEW (exceptiontable, m->exceptiontablelength);
935 count_vmcode_len += m->jcodelength + 18;
936 count_extable_len += 8 * m->exceptiontablelength;
939 for (e=0; e < m->exceptiontablelength; e++) {
941 m -> exceptiontable[e].startpc = suck_u2();
942 m -> exceptiontable[e].endpc = suck_u2();
943 m -> exceptiontable[e].handlerpc = suck_u2();
946 if (!idx) m -> exceptiontable[e].catchtype = NULL;
948 m -> exceptiontable[e].catchtype =
949 class_getconstant (c, idx, CONSTANT_Class);
953 skipattributes ( suck_u2() );
960 /********************* Funktion: method_free ***********************************
962 gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
965 *******************************************************************************/
967 static void method_free (methodinfo *m)
969 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
970 if (m->exceptiontable)
971 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
972 if (m->mcode) CFREE (m->mcode, m->mcodelength);
973 if (m->stubroutine) {
974 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
975 else removecompilerstub (m->stubroutine);
980 /************** Funktion: method_display (nur zu Debug-Zwecken) **************/
982 void method_display (methodinfo *m)
985 printflags (m -> flags);
987 utf_display (m -> name);
989 utf_display (m -> descriptor);
994 /******************** Funktion: method_canoverwrite ****************************
996 "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch
997 ist (also mit einer Methodendefinition eine andere "uberschrieben
1000 *******************************************************************************/
1002 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1004 if (m->name != old->name) return false;
1005 if (m->descriptor != old->descriptor) return false;
1006 if (m->flags & ACC_STATIC) return false;
1013 /******************************************************************************/
1014 /************************ Funktionen fuer Class *******************************/
1015 /******************************************************************************/
1018 /******************** function: class_getconstant ******************************
1020 retrieves the value at position 'pos' of the constantpool of a class
1021 if the type of the value is other than 'ctype' the system is stopped
1023 *******************************************************************************/
1025 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1027 /* invalid position in constantpool */
1028 if (pos >= c->cpcount)
1029 panic ("Attempt to access constant outside range");
1031 /* check type of constantpool entry */
1032 if (c->cptags[pos] != ctype) {
1033 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1034 (int) ctype, (int) c->cptags[pos] );
1038 return c->cpinfos[pos];
1042 /********************* Funktion: class_constanttype ****************************
1044 Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer
1047 *******************************************************************************/
1049 u4 class_constanttype (classinfo *c, u4 pos)
1051 if (pos >= c->cpcount)
1052 panic ("Attempt to access constant outside range");
1053 return c->cptags[pos];
1057 /******************** function: class_loadcpool ********************************
1059 loads the constantpool of a class,
1060 the entries are transformed into a simpler format
1061 by resolving references
1062 (a detailed overview of the compact structures can be found in global.h)
1064 *******************************************************************************/
1066 static void class_loadcpool (classinfo *c)
1069 /* The following structures are used to save information which cannot be
1070 processed during the first pass. After the complete constantpool has
1071 been traversed the references can be resolved.
1072 (only in specific order) */
1074 /* CONSTANT_Class_info entries */
1075 typedef struct forward_class {
1076 struct forward_class *next;
1081 /* CONSTANT_String */
1082 typedef struct forward_string {
1083 struct forward_string *next;
1088 /* CONSTANT_NameAndType */
1089 typedef struct forward_nameandtype {
1090 struct forward_nameandtype *next;
1094 } forward_nameandtype;
1096 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1097 typedef struct forward_fieldmethint {
1098 struct forward_fieldmethint *next;
1102 u2 nameandtype_index;
1103 } forward_fieldmethint;
1107 long int dumpsize = dump_size ();
1109 forward_class *forward_classes = NULL;
1110 forward_string *forward_strings = NULL;
1111 forward_nameandtype *forward_nameandtypes = NULL;
1112 forward_fieldmethint *forward_fieldmethints = NULL;
1114 /* number of entries in the constant_pool table */
1115 u4 cpcount = c -> cpcount = suck_u2();
1116 /* allocate memory */
1117 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1118 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1121 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1124 /* initialize constantpool */
1125 for (idx=0; idx<cpcount; idx++) {
1126 cptags[idx] = CONSTANT_UNUSED;
1127 cpinfos[idx] = NULL;
1131 /******* first pass *******/
1132 /* entries which cannot be resolved now are written into
1133 temporary structures and traversed again later */
1136 while (idx < cpcount) {
1137 /* get constant type */
1141 case CONSTANT_Class: {
1142 forward_class *nfc = DNEW(forward_class);
1144 nfc -> next = forward_classes;
1145 forward_classes = nfc;
1147 nfc -> thisindex = idx;
1148 /* reference to CONSTANT_NameAndType */
1149 nfc -> name_index = suck_u2 ();
1155 case CONSTANT_Fieldref:
1156 case CONSTANT_Methodref:
1157 case CONSTANT_InterfaceMethodref: {
1158 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1160 nff -> next = forward_fieldmethints;
1161 forward_fieldmethints = nff;
1163 nff -> thisindex = idx;
1166 /* class or interface type that contains the declaration of the field or method */
1167 nff -> class_index = suck_u2 ();
1168 /* name and descriptor of the field or method */
1169 nff -> nameandtype_index = suck_u2 ();
1175 case CONSTANT_String: {
1176 forward_string *nfs = DNEW (forward_string);
1178 nfs -> next = forward_strings;
1179 forward_strings = nfs;
1181 nfs -> thisindex = idx;
1182 /* reference to CONSTANT_Utf8_info with string characters */
1183 nfs -> string_index = suck_u2 ();
1189 case CONSTANT_NameAndType: {
1190 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1192 nfn -> next = forward_nameandtypes;
1193 forward_nameandtypes = nfn;
1195 nfn -> thisindex = idx;
1196 /* reference to CONSTANT_Utf8_info containing simple name */
1197 nfn -> name_index = suck_u2 ();
1198 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1199 nfn -> sig_index = suck_u2 ();
1205 case CONSTANT_Integer: {
1206 constant_integer *ci = NEW (constant_integer);
1209 count_const_pool_len += sizeof(constant_integer);
1212 ci -> value = suck_s4 ();
1213 cptags [idx] = CONSTANT_Integer;
1220 case CONSTANT_Float: {
1221 constant_float *cf = NEW (constant_float);
1224 count_const_pool_len += sizeof(constant_float);
1227 cf -> value = suck_float ();
1228 cptags [idx] = CONSTANT_Float;
1234 case CONSTANT_Long: {
1235 constant_long *cl = NEW(constant_long);
1238 count_const_pool_len += sizeof(constant_long);
1241 cl -> value = suck_s8 ();
1242 cptags [idx] = CONSTANT_Long;
1248 case CONSTANT_Double: {
1249 constant_double *cd = NEW(constant_double);
1252 count_const_pool_len += sizeof(constant_double);
1255 cd -> value = suck_double ();
1256 cptags [idx] = CONSTANT_Double;
1262 case CONSTANT_Utf8: {
1264 /* number of bytes in the bytes array (not string-length) */
1265 u4 length = suck_u2();
1266 cptags [idx] = CONSTANT_Utf8;
1267 /* insert utf-string into the utf-symboltable */
1268 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1269 /* skip bytes of the string */
1270 skip_nbytes(length);
1276 sprintf (logtext, "Unkown constant type: %d",(int) t);
1285 /* resolve entries in temporary structures */
1287 while (forward_classes) {
1289 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1291 if ( (name->blength>0) && (name->text[0]=='[') ) {
1292 /* check validity of descriptor */
1293 checkfielddescriptor (name->text, utf_end(name));
1295 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1296 cpinfos [forward_classes -> thisindex] =
1297 buildarraydescriptor(name->text, name->blength);
1301 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1302 /* retrieve class from class-table */
1303 cpinfos [forward_classes -> thisindex] = class_new (name);
1305 forward_classes = forward_classes -> next;
1309 while (forward_strings) {
1311 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1313 /* resolve utf-string */
1314 cptags [forward_strings -> thisindex] = CONSTANT_String;
1315 cpinfos [forward_strings -> thisindex] = text;
1317 forward_strings = forward_strings -> next;
1320 while (forward_nameandtypes) {
1321 constant_nameandtype *cn = NEW (constant_nameandtype);
1324 count_const_pool_len += sizeof(constant_nameandtype);
1327 /* resolve simple name and descriptor */
1328 cn -> name = class_getconstant
1329 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1330 cn -> descriptor = class_getconstant
1331 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1333 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1334 cpinfos [forward_nameandtypes -> thisindex] = cn;
1336 forward_nameandtypes = forward_nameandtypes -> next;
1340 while (forward_fieldmethints) {
1341 constant_nameandtype *nat;
1342 constant_FMIref *fmi = NEW (constant_FMIref);
1345 count_const_pool_len += sizeof(constant_FMIref);
1347 /* resolve simple name and descriptor */
1348 nat = class_getconstant
1349 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1351 fmi -> class = class_getconstant
1352 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1353 fmi -> name = nat -> name;
1354 fmi -> descriptor = nat -> descriptor;
1356 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1357 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1359 switch (forward_fieldmethints -> tag) {
1360 case CONSTANT_Fieldref: /* check validity of descriptor */
1361 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1363 case CONSTANT_InterfaceMethodref:
1364 case CONSTANT_Methodref: /* check validity of descriptor */
1365 checkmethoddescriptor (fmi->descriptor);
1369 forward_fieldmethints = forward_fieldmethints -> next;
1374 dump_release (dumpsize);
1378 /********************** Funktion: class_load ***********************************
1380 l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
1381 'classinfo'-Struktur mu"s bereits angelegt worden sein.
1383 Die Superklasse und die Interfaces, die diese Klasse implementiert,
1384 m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die
1385 Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
1387 Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
1388 und in die Liste 'unlinkedclasses' eingh"angt.
1390 *******************************************************************************/
1392 static int class_load (classinfo *c)
1398 count_class_loads++;
1401 /* output for debugging purposes */
1403 sprintf (logtext, "Loading class: ");
1404 utf_sprint (logtext+strlen(logtext), c->name );
1408 /* load classdata, throw exception on error */
1409 if (!suck_start (c->name)) {
1410 throw_classnotfoundexception();
1414 /* check signature */
1415 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1419 if (ma != MAJOR_VERSION) {
1420 sprintf (logtext, "Can only support major version %d, but not %d",
1421 MAJOR_VERSION, (int) ma);
1424 if (mi > MINOR_VERSION) {
1425 sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
1430 class_loadcpool (c);
1433 c -> flags = suck_u2 ();
1437 /* retrieve superclass */
1438 if ( (i = suck_u2 () ) ) {
1439 c -> super = class_getconstant (c, i, CONSTANT_Class);
1445 /* retrieve interfaces */
1446 c -> interfacescount = suck_u2 ();
1447 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1448 for (i=0; i < c -> interfacescount; i++) {
1449 c -> interfaces [i] =
1450 class_getconstant (c, suck_u2(), CONSTANT_Class);
1454 c -> fieldscount = suck_u2 ();
1455 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1456 for (i=0; i < c -> fieldscount; i++) {
1457 field_load (&(c->fields[i]), c);
1461 c -> methodscount = suck_u2 ();
1462 c -> methods = MNEW (methodinfo, c -> methodscount);
1463 for (i=0; i < c -> methodscount; i++) {
1464 method_load (&(c -> methods [i]), c);
1468 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1469 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1470 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1473 /* load variable-length attribute structures */
1474 attribute_load (suck_u2(), c);
1479 /* remove class from list of unloaded classes and
1480 add to list of unlinked classes */
1481 list_remove (&unloadedclasses, c);
1482 list_addlast (&unlinkedclasses, c);
1489 /************** interne Funktion: class_highestinterface ***********************
1491 wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
1492 die Interfacetable einer Klasse sein mu"s.
1494 *******************************************************************************/
1496 static s4 class_highestinterface (classinfo *c)
1501 if ( ! (c->flags & ACC_INTERFACE) ) {
1502 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1503 utf_sprint (logtext+strlen(logtext), c->name);
1508 for (i=0; i<c->interfacescount; i++) {
1509 s4 h2 = class_highestinterface (c->interfaces[i]);
1516 /* class_addinterface **********************************************************
1518 wird von der Funktion class_link ben"otigt, um eine Virtual Function
1519 Table f"ur ein Interface (und alle weiteren von diesem Interface
1520 implementierten Interfaces) in eine Klasse einzutragen.
1522 *******************************************************************************/
1524 static void class_addinterface (classinfo *c, classinfo *ic)
1528 vftbl *vftbl = c->vftbl;
1530 if (i >= vftbl->interfacetablelength)
1531 panic ("Inernal error: interfacetable overflow");
1532 if (vftbl->interfacetable[-i])
1535 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1536 vftbl->interfacevftbllength[i] = 1;
1537 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1538 vftbl->interfacetable[-i][0] = NULL;
1541 vftbl->interfacevftbllength[i] = ic->methodscount;
1542 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1545 count_vftbl_len += sizeof(methodptr) *
1546 (ic->methodscount + (ic->methodscount == 0));
1549 for (j=0; j<ic->methodscount; j++) {
1552 for (m = 0; m < sc->methodscount; m++) {
1553 methodinfo *mi = &(sc->methods[m]);
1554 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1555 vftbl->interfacetable[-i][j] =
1556 vftbl->table[mi->vftblindex];
1566 for (j = 0; j < ic->interfacescount; j++)
1567 class_addinterface(c, ic->interfaces[j]);
1571 /********************** Funktion: class_link ***********************************
1573 versucht, eine Klasse in das System voll zu integrieren (linken). Dazu
1574 m"ussen sowol die Superklasse, als auch alle implementierten
1575 Interfaces schon gelinkt sein.
1576 Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz
1577 dieser Klasse, als auch die Virtual Function Tables f"ur normale
1578 Methoden als auch Interface-Methoden.
1580 Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
1581 der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
1583 Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
1585 Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
1586 eine Endlosschleife!! (Da muss ich mir noch was einfallen lassen)
1588 *******************************************************************************/
1590 static void class_link (classinfo *c)
1592 s4 supervftbllength; /* vftbllegnth of super class */
1593 s4 vftbllength; /* vftbllength of current class */
1594 s4 interfacetablelength; /* interface table length */
1595 classinfo *super = c->super; /* super class */
1596 classinfo *ic, *c2; /* intermediate class variables */
1597 vftbl *v; /* vftbl of current class */
1598 s4 i; /* interface/method/field counter */
1601 /* check if all superclasses are already linked, if not put c at end of
1602 unlinked list and return. Additionally initialize class fields. */
1604 /* check interfaces */
1606 for (i = 0; i < c->interfacescount; i++) {
1607 ic = c->interfaces[i];
1609 list_remove(&unlinkedclasses, c);
1610 list_addlast(&unlinkedclasses, c);
1615 /* check super class */
1617 if (super == NULL) { /* class java.long.Object */
1619 c->instancesize = sizeof(java_objectheader);
1621 vftbllength = supervftbllength = 0;
1623 c->finalizer = NULL;
1626 if (!super->linked) {
1627 list_remove(&unlinkedclasses, c);
1628 list_addlast(&unlinkedclasses, c);
1632 if (c->flags & ACC_INTERFACE)
1633 c->index = interfaceindex++;
1635 c->index = super->index + 1;
1637 c->instancesize = super->instancesize;
1639 vftbllength = supervftbllength = super->vftbl->vftbllength;
1641 c->finalizer = super->finalizer;
1646 sprintf (logtext, "Linking Class: ");
1647 utf_sprint (logtext+strlen(logtext), c->name );
1651 /* compute vftbl length */
1653 for (i = 0; i < c->methodscount; i++) {
1654 methodinfo *m = &(c->methods[i]);
1656 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1657 classinfo *sc = super;
1660 for (j = 0; j < sc->methodscount; j++) {
1661 if (method_canoverwrite(m, &(sc->methods[j]))) {
1662 m->vftblindex = sc->methods[j].vftblindex;
1663 goto foundvftblindex;
1668 m->vftblindex = (vftbllength++);
1674 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1677 /* compute interfacetable length */
1679 interfacetablelength = 0;
1682 for (i = 0; i < c2->interfacescount; i++) {
1683 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1684 if (h > interfacetablelength)
1685 interfacetablelength = h;
1690 /* allocate virtual function table */
1692 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1693 (vftbllength - 1) + sizeof(methodptr*) *
1694 (interfacetablelength - (interfacetablelength > 0)));
1695 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1696 (interfacetablelength > 1));
1697 c->header.vftbl = c->vftbl = v;
1699 v->vftbllength = vftbllength;
1700 v->interfacetablelength = interfacetablelength;
1702 /* copy virtual function table of super class */
1704 for (i = 0; i < supervftbllength; i++)
1705 v->table[i] = super->vftbl->table[i];
1707 /* add method stubs into virtual function table */
1709 for (i = 0; i < c->methodscount; i++) {
1710 methodinfo *m = &(c->methods[i]);
1711 if (!(m->flags & ACC_STATIC)) {
1712 v->table[m->vftblindex] = m->stubroutine;
1716 /* compute instance size and offset of each field */
1718 for (i = 0; i < c->fieldscount; i++) {
1720 fieldinfo *f = &(c->fields[i]);
1722 if (!(f->flags & ACC_STATIC) ) {
1723 dsize = desc_typesize (f->descriptor);
1724 c->instancesize = ALIGN (c->instancesize, dsize);
1725 f->offset = c->instancesize;
1726 c->instancesize += dsize;
1730 /* initialize interfacetable and interfacevftbllength */
1732 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1735 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1738 for (i = 0; i < interfacetablelength; i++) {
1739 v->interfacevftbllength[i] = 0;
1740 v->interfacetable[-i] = NULL;
1743 /* add interfaces */
1745 for (c2 = c; c2 != NULL; c2 = c2->super)
1746 for (i = 0; i < c2->interfacescount; i++) {
1747 class_addinterface (c, c2->interfaces[i]);
1750 /* add finalizer method (not for java.lang.Object) */
1752 if (super != NULL) {
1754 static utf *finame = NULL;
1755 static utf *fidesc = NULL;
1758 finame = utf_finalize;
1760 fidesc = utf_fidesc;
1762 fi = class_findmethod (c, finame, fidesc);
1764 if (!(fi->flags & ACC_STATIC)) {
1774 list_remove (&unlinkedclasses, c);
1775 list_addlast (&linkedclasses, c);
1779 /******************* Funktion: class_freepool **********************************
1781 Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
1784 *******************************************************************************/
1786 static void class_freecpool (classinfo *c)
1792 for (idx=0; idx < c->cpcount; idx++) {
1793 tag = c->cptags[idx];
1794 info = c->cpinfos[idx];
1798 case CONSTANT_Fieldref:
1799 case CONSTANT_Methodref:
1800 case CONSTANT_InterfaceMethodref:
1801 FREE (info, constant_FMIref);
1803 case CONSTANT_Integer:
1804 FREE (info, constant_integer);
1806 case CONSTANT_Float:
1807 FREE (info, constant_float);
1810 FREE (info, constant_long);
1812 case CONSTANT_Double:
1813 FREE (info, constant_double);
1815 case CONSTANT_NameAndType:
1816 FREE (info, constant_nameandtype);
1818 case CONSTANT_Arraydescriptor:
1819 freearraydescriptor (info);
1825 MFREE (c -> cptags, u1, c -> cpcount);
1826 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1830 /*********************** Funktion: class_free **********************************
1832 Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
1834 *******************************************************************************/
1836 static void class_free (classinfo *c)
1841 class_freecpool (c);
1843 MFREE (c->interfaces, classinfo*, c->interfacescount);
1845 for (i = 0; i < c->fieldscount; i++)
1846 field_free(&(c->fields[i]));
1847 MFREE (c->fields, fieldinfo, c->fieldscount);
1849 for (i = 0; i < c->methodscount; i++)
1850 method_free(&(c->methods[i]));
1851 MFREE (c->methods, methodinfo, c->methodscount);
1853 if ((v = c->vftbl) != NULL) {
1854 for (i = 0; i < v->interfacetablelength; i++) {
1855 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1857 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1859 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1860 sizeof(methodptr*) * (v->interfacetablelength -
1861 (v->interfacetablelength > 0));
1862 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1863 (v->interfacetablelength > 1));
1867 if (c->innerclasscount)
1868 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1870 FREE (c, classinfo);
1873 /************************* Funktion: class_findfield ***************************
1875 sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
1878 *******************************************************************************/
1881 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1885 for (i = 0; i < c->fieldscount; i++) {
1886 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1887 return &(c->fields[i]);
1890 panic ("Can not find field given in CONSTANT_Fieldref");
1895 /************************* Funktion: class_findmethod **************************
1897 sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1899 Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1901 *******************************************************************************/
1903 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1906 for (i = 0; i < c->methodscount; i++) {
1907 if ((c->methods[i].name == name) && ((desc == NULL) ||
1908 (c->methods[i].descriptor == desc)))
1909 return &(c->methods[i]);
1914 /************************* Funktion: class_findmethod_approx ******************
1916 sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1918 Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1919 beim Vergleichen des Descriptors wird der R"uckgabewert nicht betrachtet
1921 *******************************************************************************/
1923 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1927 for (i = 0; i < c->methodscount; i++)
1928 if (c->methods[i].name == name) {
1929 utf *meth_descr = c->methods[i].descriptor;
1933 return &(c->methods[i]);
1935 if (desc->blength <= meth_descr->blength) {
1936 /* current position in utf text */
1937 char *desc_utf_ptr = desc->text;
1938 char *meth_utf_ptr = meth_descr->text;
1939 /* points behind utf strings */
1940 char *desc_end = utf_end(desc);
1941 char *meth_end = utf_end(meth_descr);
1944 /* compare argument types */
1945 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1947 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1948 break; /* no match */
1951 return &(c->methods[i]); /* all parameter types equal */
1959 /***************** Funktion: class_resolvemethod_approx ***********************
1961 sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1962 (ohne Beachtung des R"uckgabewertes)
1964 *******************************************************************************/
1966 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1969 /* search for method (ignore returntype) */
1970 methodinfo *m = class_findmethod_approx (c, name, desc);
1973 /* search superclass */
1980 /************************* Funktion: class_resolvemethod ***********************
1982 sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1984 *******************************************************************************/
1987 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
1990 methodinfo *m = class_findmethod (c, name, desc);
1992 /* search superclass */
2000 /************************* Funktion: class_issubclass **************************
2002 "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.
2004 *******************************************************************************/
2006 bool class_issubclass (classinfo *sub, classinfo *super)
2009 if (!sub) return false;
2010 if (sub==super) return true;
2017 /****************** Initialisierungsfunktion f"ur eine Klasse ******************
2019 In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
2020 Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
2021 Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
2024 *******************************************************************************/
2027 extern int blockInts;
2030 void class_init (classinfo *c)
2033 java_objectheader *exceptionptr;
2037 if (!makeinitializations)
2041 c -> initialized = true;
2044 count_class_inits++;
2048 class_init (c->super);
2049 for (i=0; i < c->interfacescount; i++)
2050 class_init(c->interfaces[i]);
2052 m = class_findmethod (c, utf_clinit, utf_fidesc);
2055 sprintf (logtext, "Class ");
2056 utf_sprint (logtext+strlen(logtext), c->name);
2057 sprintf (logtext+strlen(logtext), " has no initializer");
2063 if (! (m->flags & ACC_STATIC))
2064 panic ("Class initializer is not static!");
2067 sprintf (logtext, "Starting initializer for class: ");
2068 utf_sprint (logtext+strlen(logtext), c->name);
2077 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2080 assert(blockInts == 0);
2085 printf ("#### Initializer of ");
2086 utf_display (c->name);
2087 printf (" has thrown: ");
2088 utf_display (exceptionptr->vftbl->class->name);
2094 sprintf (logtext, "Finished initializer for class: ");
2095 utf_sprint (logtext+strlen(logtext), c->name);
2099 if (c->name == utf_systemclass) {
2100 /* class java.lang.System requires explicit initialization */
2103 printf ("#### Initializing class System");
2105 /* find initializing method */
2106 m = class_findmethod (c,
2107 utf_initsystemclass,
2111 /* no method found */
2112 log("initializeSystemClass failed");
2121 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2124 assert(blockInts == 0);
2129 printf ("#### initializeSystemClass has thrown: ");
2130 utf_display (exceptionptr->vftbl->class->name);
2140 /********* Funktion: class_showconstantpool (nur f"ur Debug-Zwecke) *********/
2142 void class_showconstantpool (classinfo *c)
2147 printf ("---- dump of constant pool ----\n");
2149 for (i=0; i<c->cpcount; i++) {
2150 printf ("#%d: ", (int) i);
2152 e = c -> cpinfos [i];
2155 switch (c -> cptags [i]) {
2156 case CONSTANT_Class:
2157 printf ("Classreference -> ");
2158 utf_display ( ((classinfo*)e) -> name );
2161 case CONSTANT_Fieldref:
2162 printf ("Fieldref -> "); goto displayFMI;
2163 case CONSTANT_Methodref:
2164 printf ("Methodref -> "); goto displayFMI;
2165 case CONSTANT_InterfaceMethodref:
2166 printf ("InterfaceMethod -> "); goto displayFMI;
2169 constant_FMIref *fmi = e;
2170 utf_display ( fmi->class->name );
2172 utf_display ( fmi->name);
2174 utf_display ( fmi->descriptor );
2178 case CONSTANT_String:
2179 printf ("String -> ");
2182 case CONSTANT_Integer:
2183 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2185 case CONSTANT_Float:
2186 printf ("Float -> %f", ((constant_float*)e) -> value);
2188 case CONSTANT_Double:
2189 printf ("Double -> %f", ((constant_double*)e) -> value);
2193 u8 v = ((constant_long*)e) -> value;
2195 printf ("Long -> %ld", (long int) v);
2197 printf ("Long -> HI: %ld, LO: %ld\n",
2198 (long int) v.high, (long int) v.low);
2202 case CONSTANT_NameAndType:
2203 { constant_nameandtype *cnt = e;
2204 printf ("NameAndType: ");
2205 utf_display (cnt->name);
2207 utf_display (cnt->descriptor);
2211 printf ("Utf8 -> ");
2214 case CONSTANT_Arraydescriptor: {
2215 printf ("Arraydescriptor: ");
2216 displayarraydescriptor (e);
2220 panic ("Invalid type of ConstantPool-Entry");
2232 /********** Funktion: class_showmethods (nur f"ur Debug-Zwecke) *************/
2234 void class_showmethods (classinfo *c)
2238 printf ("--------- Fields and Methods ----------------\n");
2239 printf ("Flags: "); printflags (c->flags); printf ("\n");
2241 printf ("This: "); utf_display (c->name); printf ("\n");
2243 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2245 printf ("Index: %d\n", c->index);
2247 printf ("interfaces:\n");
2248 for (i=0; i < c-> interfacescount; i++) {
2250 utf_display (c -> interfaces[i] -> name);
2251 printf (" (%d)\n", c->interfaces[i] -> index);
2254 printf ("fields:\n");
2255 for (i=0; i < c -> fieldscount; i++) {
2256 field_display (&(c -> fields[i]));
2259 printf ("methods:\n");
2260 for (i=0; i < c -> methodscount; i++) {
2261 methodinfo *m = &(c->methods[i]);
2262 if ( !(m->flags & ACC_STATIC))
2263 printf ("vftblindex: %d ", m->vftblindex);
2265 method_display ( m );
2269 printf ("Virtual function table:\n");
2270 for (i=0; i<c->vftbl->vftbllength; i++) {
2271 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2278 /******************************************************************************/
2279 /******************* Funktionen fuer den Class-loader generell ****************/
2280 /******************************************************************************/
2282 static int loader_inited = 0;
2284 /********************* Funktion: loader_load ***********************************
2286 l"adt und linkt die ge"unschte Klasse und alle davon
2287 referenzierten Klassen und Interfaces
2288 Return: Einen Zeiger auf diese Klasse
2290 *******************************************************************************/
2292 classinfo *loader_load (utf *topname)
2296 long int starttime=0,stoptime=0;
2298 intsDisable(); /* schani */
2301 starttime = getcputime();
2303 top = class_new (topname);
2306 while ( (c = list_first(&unloadedclasses)) ) {
2307 if (!class_load (c)) {
2308 list_remove (&unloadedclasses, c);
2314 while ( (c = list_first(&unlinkedclasses)) ) {
2319 loader_compute_subclasses();
2322 if (getloadingtime) {
2323 stoptime = getcputime();
2324 loadingtime += (stoptime-starttime);
2327 intsRestore(); /* schani */
2333 /**************** function: create_primitive_classes ***************************
2335 create classes representing primitive types
2337 ********************************************************************************/
2340 void create_primitive_classes()
2344 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2345 /* create primitive class */
2346 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2348 /* prevent loader from loading primitive class */
2349 list_remove (&unloadedclasses, c);
2350 /* add to unlinked classes */
2351 list_addlast (&unlinkedclasses, c);
2352 c -> super = class_java_lang_Object;
2355 primitivetype_table[i].class_primitive = c;
2357 /* create class for wrapping the primitive type */
2358 primitivetype_table[i].class_wrap =
2359 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2363 /***************** function: create_array_class ********************************
2365 create class representing an array
2367 ********************************************************************************/
2370 classinfo *create_array_class(utf *u)
2372 classinfo *c = class_new (u);
2373 /* prevent loader from loading the array class */
2374 list_remove (&unloadedclasses, c);
2375 /* add to unlinked classes */
2376 list_addlast (&unlinkedclasses, c);
2377 c -> super = class_java_lang_Object;
2383 /********************** Funktion: loader_init **********************************
2385 Initialisiert alle Listen und l"adt alle Klassen, die vom System
2386 und vom Compiler direkt ben"otigt werden.
2388 *******************************************************************************/
2395 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2396 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2397 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2399 /* create utf-symbols for pointer comparison of frequently used strings */
2400 utf_innerclasses = utf_new_char("InnerClasses");
2401 utf_constantvalue = utf_new_char("ConstantValue");
2402 utf_code = utf_new_char("Code");
2403 utf_finalize = utf_new_char("finalize");
2404 utf_fidesc = utf_new_char("()V");
2405 utf_clinit = utf_new_char("<clinit>");
2406 utf_initsystemclass = utf_new_char("initializeSystemClass");
2407 utf_systemclass = utf_new_char("java/lang/System");
2409 /* create class for arrays */
2410 class_array = class_new ( utf_new_char ("The_Array_Class") );
2411 list_remove (&unloadedclasses, class_array);
2413 /* create class for strings, load it after class Object was loaded */
2414 string_class = utf_new_char ("java/lang/String");
2415 class_java_lang_String = class_new(string_class);
2416 list_remove (&unloadedclasses, class_java_lang_String);
2418 class_java_lang_Object =
2419 loader_load ( utf_new_char ("java/lang/Object") );
2421 list_addlast(&unloadedclasses, class_java_lang_String);
2423 class_java_lang_String =
2424 loader_load ( string_class );
2425 class_java_lang_ClassCastException =
2426 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2427 class_java_lang_NullPointerException =
2428 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2429 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2430 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2431 class_java_lang_NegativeArraySizeException = loader_load (
2432 utf_new_char ("java/lang/NegativeArraySizeException") );
2433 class_java_lang_OutOfMemoryError = loader_load (
2434 utf_new_char ("java/lang/OutOfMemoryError") );
2435 class_java_lang_ArrayStoreException =
2436 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2437 class_java_lang_ArithmeticException =
2438 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2439 class_java_lang_ThreadDeath = /* schani */
2440 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2442 /* link class for arrays */
2443 list_addlast (&unlinkedclasses, class_array);
2444 class_array -> super = class_java_lang_Object;
2445 class_link (class_array);
2447 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2448 stringtable_update();
2450 /* create classes representing primitive types */
2451 create_primitive_classes();
2453 proto_java_lang_ClassCastException =
2454 builtin_new(class_java_lang_ClassCastException);
2455 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2457 proto_java_lang_NullPointerException =
2458 builtin_new(class_java_lang_NullPointerException);
2459 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2461 proto_java_lang_ArrayIndexOutOfBoundsException =
2462 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2463 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2465 proto_java_lang_NegativeArraySizeException =
2466 builtin_new(class_java_lang_NegativeArraySizeException);
2467 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2469 proto_java_lang_OutOfMemoryError =
2470 builtin_new(class_java_lang_OutOfMemoryError);
2471 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2473 proto_java_lang_ArithmeticException =
2474 builtin_new(class_java_lang_ArithmeticException);
2475 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2477 proto_java_lang_ArrayStoreException =
2478 builtin_new(class_java_lang_ArrayStoreException);
2479 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2481 proto_java_lang_ThreadDeath = /* schani */
2482 builtin_new(class_java_lang_ThreadDeath);
2483 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2491 /********************* Funktion: loader_initclasses ****************************
2493 initialisiert alle geladenen aber noch nicht initialisierten Klassen
2495 *******************************************************************************/
2497 void loader_initclasses ()
2501 intsDisable(); /* schani */
2503 if (makeinitializations) {
2504 c = list_first (&linkedclasses);
2507 c = list_next (&linkedclasses, c);
2511 intsRestore(); /* schani */
2514 static s4 classvalue;
2516 static void loader_compute_class_values (classinfo *c)
2520 c->vftbl->baseval = ++classvalue;
2522 while (subs != NULL) {
2523 loader_compute_class_values(subs);
2524 subs = subs->nextsub;
2526 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2530 for (i = 0; i < c->index; i++)
2532 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2533 utf_display(c->name);
2540 void loader_compute_subclasses ()
2544 intsDisable(); /* schani */
2546 c = list_first (&linkedclasses);
2548 if (!(c->flags & ACC_INTERFACE)) {
2552 c = list_next (&linkedclasses, c);
2555 c = list_first (&linkedclasses);
2557 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2558 c->nextsub = c->super->sub;
2561 c = list_next (&linkedclasses, c);
2565 loader_compute_class_values(class_java_lang_Object);
2567 intsRestore(); /* schani */
2572 /******************** function classloader_buffer ******************************
2574 sets buffer for reading classdata
2576 *******************************************************************************/
2578 void classload_buffer(u1 *buf, int len)
2581 classbuffer_size = len;
2582 classbuf_pos = buf - 1;
2586 /******************** Funktion: loader_close ***********************************
2588 gibt alle Resourcen wieder frei
2590 *******************************************************************************/
2592 void loader_close ()
2596 while ( (c=list_first(&unloadedclasses)) ) {
2597 list_remove (&unloadedclasses,c);
2600 while ( (c=list_first(&unlinkedclasses)) ) {
2601 list_remove (&unlinkedclasses,c);
2604 while ( (c=list_first(&linkedclasses)) ) {
2605 list_remove (&linkedclasses,c);
2612 * These are local overrides for various environment variables in Emacs.
2613 * Please do not remove this and leave it at the end of the file, where
2614 * Emacs will automagically detect them.
2615 * ---------------------------------------------------------------------
2618 * indent-tabs-mode: t