2 /* loader.c ********************************************************************
4 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, 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: Mark Probst EMAIL: cacao@complang.tuwien.ac.at
13 Last Change: 1997/06/03
15 *******************************************************************************/
31 #include "threads/thread.h" /* schani */
34 /* global variables ***********************************************************/
36 extern bool newcompiler; /* true if new compiler is used */
38 int count_class_infos = 0; /* variables for measurements */
39 int count_const_pool_len = 0;
40 int count_vftbl_len = 0;
41 int count_all_methods = 0;
42 int count_vmcode_len = 0;
43 int count_extable_len = 0;
45 bool loadverbose = false; /* switches for debug messages */
46 bool linkverbose = false;
47 bool initverbose = false;
49 bool makeinitializations = true;
51 bool getloadingtime = false; /* to measure the runtime */
52 long int loadingtime = 0;
54 static s4 interfaceindex; /* sequential numbering of interfaces */
56 list unloadedclasses; /* list of all referenced but not loaded classes */
57 list unlinkedclasses; /* list of all loaded but not linked classes */
58 list linkedclasses; /* list of all completely linked classes */
61 /* utf-symbols for pointer comparison of frequently used strings */
63 static utf *utf_innerclasses; /* InnerClasses */
64 static utf *utf_constantvalue; /* ConstantValue */
65 static utf *utf_code; /* Code */
66 static utf *utf_finalize; /* finalize */
67 static utf *utf_fidesc; /* ()V */
68 static utf *utf_clinit; /* <clinit> */
69 static utf *utf_initsystemclass; /* initializeSystemClass */
70 static utf *utf_systemclass; /* java/lang/System */
72 /* important system classes ***************************************************/
74 classinfo *class_java_lang_Object;
75 classinfo *class_java_lang_String;
76 classinfo *class_java_lang_ClassCastException;
77 classinfo *class_java_lang_NullPointerException;
78 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
79 classinfo *class_java_lang_NegativeArraySizeException;
80 classinfo *class_java_lang_OutOfMemoryError;
81 classinfo *class_java_lang_ArithmeticException;
82 classinfo *class_java_lang_ArrayStoreException;
83 classinfo *class_java_lang_ThreadDeath; /* schani */
84 classinfo *class_array = NULL;
86 /******************************************************************************
88 structure for primitive classes: contains the class for wrapping the
89 primitive type, the primitive class, the name of the class for wrapping,
90 the one character type signature and the name of the primitive class
92 ******************************************************************************/
94 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
95 { NULL, NULL, "java/lang/Double", 'D', "double" },
96 { NULL, NULL, "java/lang/Float", 'F', "float" },
97 { NULL, NULL, "java/lang/Character", 'C', "char" },
98 { NULL, NULL, "java/lang/Integer", 'I', "int" },
99 { NULL, NULL, "java/lang/Long", 'J', "long" },
100 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
101 { NULL, NULL, "java/lang/Short", 'S', "short" },
102 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
103 { NULL, NULL, "java/lang/Void", 'V', "void" }};
105 /* instances of important system classes **************************************/
107 java_objectheader *proto_java_lang_ClassCastException;
108 java_objectheader *proto_java_lang_NullPointerException;
109 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
110 java_objectheader *proto_java_lang_NegativeArraySizeException;
111 java_objectheader *proto_java_lang_OutOfMemoryError;
112 java_objectheader *proto_java_lang_ArithmeticException;
113 java_objectheader *proto_java_lang_ArrayStoreException;
114 java_objectheader *proto_java_lang_ThreadDeath; /* schani */
117 /************* functions for reading classdata ********************************
119 getting classdata in blocks of variable size
120 (8,16,32,64-bit integer or float)
122 *******************************************************************************/
124 static char *classpath = ""; /* searchpath for classfiles */
125 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
126 static u1 *classbuf_pos; /* current position in classfile buffer */
127 static int classbuffer_size; /* size of classfile-data */
129 /* transfer block of classfile data into a buffer */
130 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len);classbuf_pos+=len;
132 /* skip block of classfile data */
133 #define skip_nbytes(len) classbuf_pos += len;
135 #define suck_u1() (*++classbuf_pos)
136 #define suck_s8() (s8) suck_u8()
137 #define suck_s2() (s2) suck_u2()
138 #define suck_s4() (s4) suck_u4()
139 #define suck_s1() (s1) suck_u1()
140 #define suck_u2() (u2) ((suck_u1()<<8)+suck_u1())
141 #define suck_u4() (u4) ((((u4)suck_u1())<<24)+(((u4)suck_u1())<<16)+(((u4)suck_u1())<<8)+((u4)suck_u1()))
143 /* get u8 from classfile data */
150 return (hi<<32) + lo;
159 /* get float from classfile data */
160 static float suck_float ()
167 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
168 memcpy ( (u1*) (&f), buffer, 4);
170 suck_nbytes ( (u1*) (&f), 4 );
173 PANICIF (sizeof(float) != 4, "Incompatible float-format");
178 /* get double from classfile data */
179 static double suck_double ()
186 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
187 memcpy ( (u1*) (&d), buffer, 8);
189 suck_nbytes ( (u1*) (&d), 8 );
192 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
197 /************************** function: suck_init ******************************
199 called once at startup, sets the searchpath for the classfiles
201 ******************************************************************************/
203 void suck_init (char *cpath)
210 /************************** function: suck_start ******************************
212 open file for the specified class and the read classfile data,
213 all directory of the searchpath are used to find the classfile
216 ******************************************************************************/
219 bool suck_start (utf *classname)
221 #define MAXFILENAME 1000 /* maximum length of a filename */
223 char filename[MAXFILENAME+10]; /* room for '.class' */
224 char *pathpos; /* position in searchpath */
229 if (classbuffer) /* classbuffer already valid */
235 /* pointer to the next utf8-character */
236 char *utf_ptr = classname->text;
238 /* skip path separator */
239 while ( *pathpos == ':' ) pathpos++;
241 /* extract directory from searchpath */
243 while ( (*pathpos) && (*pathpos!=':') ) {
244 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
246 filename[filenamelen++] = *(pathpos++);
249 filename[filenamelen++] = '/';
251 /* add classname to filename */
252 while (utf_ptr<utf_end(classname)) {
253 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
258 if ( c<=' ' || c>'z') {
259 /* invalid character */
264 filename[filenamelen++] = c;
268 strcpy (filename+filenamelen, ".class");
270 classfile = fopen(filename, "r");
276 /* determine size of classfile */
277 err = stat (filename, &buffer);
280 /* read classfile data */
281 classbuffer_size = buffer.st_size;
282 classbuffer = MNEW(u1,classbuffer_size);
283 classbuf_pos = classbuffer-1;
284 fread(classbuffer, 1, classbuffer_size, classfile);
291 sprintf (logtext,"Can not open class file '%s'", filename);
298 /************************** function: suck_stop *******************************
300 free memory for buffer with classfile data
302 ******************************************************************************/
306 /* determine number of bytes of classdata not retrieved by suck-operations */
307 int classdata_left = (classbuffer+classbuffer_size)-classbuf_pos-1;
309 if (classdata_left>0) {
311 sprintf (logtext,"There are %d access bytes at end of classfile",
317 MFREE(classbuffer,u1,classbuffer_size);
321 /******************************************************************************/
322 /******************* Einige Support-Funkionen *********************************/
323 /******************************************************************************/
326 /********** interne Funktion: printflags (nur zu Debug-Zwecken) **************/
328 static void printflags (u2 f)
330 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
331 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
332 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
333 if ( f & ACC_STATIC ) printf (" STATIC");
334 if ( f & ACC_FINAL ) printf (" FINAL");
335 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
336 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
337 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
338 if ( f & ACC_NATIVE ) printf (" NATIVE");
339 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
340 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
344 /************************* Funktion: skipattribute *****************************
346 "uberliest im ClassFile eine (1) 'attribute'-Struktur
348 *******************************************************************************/
350 static void skipattribute ()
353 skip_nbytes(suck_u4());
356 /********************** Funktion: skipattributebody ****************************
358 "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name -
359 Referenz schon gelesen worden ist.
361 *******************************************************************************/
363 static void skipattributebody ()
365 skip_nbytes(suck_u4());
368 /************************* Funktion: skipattributes ****************************
370 "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
372 *******************************************************************************/
374 static void skipattributes (u4 num)
377 for (i = 0; i < num; i++)
381 /******************** function: innerclass_getconstant ************************
383 like class_getconstant, but if cptags is ZERO null is returned
385 *******************************************************************************/
387 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
389 /* invalid position in constantpool */
390 if (pos >= c->cpcount)
391 panic ("Attempt to access constant outside range");
393 /* constantpool entry of type 0 */
397 /* check type of constantpool entry */
398 if (c->cptags[pos] != ctype) {
399 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
400 (int) ctype, (int) c->cptags[pos] );
404 return c->cpinfos[pos];
407 /************************ function: attribute_load ****************************
409 read attributes from classfile
411 *******************************************************************************/
413 static void attribute_load (u4 num, classinfo *c)
417 for (i = 0; i < num; i++) {
418 /* retrieve attribute name */
419 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
421 if ( aname == utf_innerclasses) {
422 /* innerclasses attribute */
424 /* skip attribute length */
426 /* number of records */
427 c->innerclasscount = suck_u2();
428 /* allocate memory for innerclass structure */
429 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
431 for (j=0;j<c->innerclasscount;j++) {
433 /* The innerclass structure contains a class with an encoded name,
434 its defining scope, its simple name and a bitmask of the access flags.
435 If an inner class is not a member, its outer_class is NULL,
436 if a class is anonymous, its name is NULL. */
438 innerclassinfo *info = c->innerclass + j;
440 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
441 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
442 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
443 info->flags = suck_u2 (); /* access_flags bitmask */
446 /* unknown attribute */
447 skipattributebody ();
452 /******************* function: checkfielddescriptor ****************************
454 checks whether a field-descriptor is valid and aborts otherwise
455 all referenced classes are inserted into the list of unloaded classes
457 *******************************************************************************/
459 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
461 char *tstart; /* pointer to start of classname */
464 switch (*utf_ptr++) {
477 /* save start of classname */
480 /* determine length of classname */
481 while ( *utf_ptr++ != ';' )
482 if (utf_ptr>=end_pos)
483 panic ("Missing ';' in objecttype-descriptor");
485 /* cause loading of referenced class */
486 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
491 while ((ch = *utf_ptr++)=='[')
494 /* component type of array */
508 /* save start of classname */
511 /* determine length of classname */
512 while ( *utf_ptr++ != ';' )
513 if (utf_ptr>=end_pos)
514 panic ("Missing ';' in objecttype-descriptor");
516 /* cause loading of referenced class */
517 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
521 panic ("Ill formed methodtype-descriptor");
526 panic ("Ill formed methodtype-descriptor");
529 /* exceeding characters */
530 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
534 /******************* function: checkmethoddescriptor ***************************
536 checks whether a method-descriptor is valid and aborts otherwise
537 all referenced classes are inserted into the list of unloaded classes
539 *******************************************************************************/
541 static void checkmethoddescriptor (utf *d)
543 char *utf_ptr = d->text; /* current position in utf text */
544 char *end_pos = utf_end(d); /* points behind utf string */
545 char *tstart; /* pointer to start of classname */
548 /* method descriptor must start with parenthesis */
549 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
551 /* check arguments */
552 while ((c = *utf_ptr++) != ')') {
566 /* save start of classname */
569 /* determine length of classname */
570 while ( *utf_ptr++ != ';' )
571 if (utf_ptr>=end_pos)
572 panic ("Missing ';' in objecttype-descriptor");
574 /* cause loading of referenced class */
575 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
580 while ((ch = *utf_ptr++)=='[')
583 /* component type of array */
597 /* save start of classname */
600 /* determine length of classname */
601 while ( *utf_ptr++ != ';' )
602 if (utf_ptr>=end_pos)
603 panic ("Missing ';' in objecttype-descriptor");
605 /* cause loading of referenced class */
606 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
610 panic ("Ill formed methodtype-descriptor");
615 panic ("Ill formed methodtype-descriptor");
619 /* check returntype */
621 /* returntype void */
622 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
625 /* treat as field-descriptor */
626 checkfielddescriptor (utf_ptr,end_pos);
630 /******************** Funktion: buildarraydescriptor ***************************
632 erzeugt zu einem namentlich als utf-String vorliegenden Arraytyp eine
633 entsprechende constant_arraydescriptor - Struktur
635 *******************************************************************************/
637 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
639 constant_arraydescriptor *d;
641 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
643 d = NEW (constant_arraydescriptor);
644 d -> objectclass = NULL;
645 d -> elementdescriptor = NULL;
648 count_const_pool_len += sizeof(constant_arraydescriptor);
652 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
653 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
654 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
655 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
656 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
657 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
658 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
659 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
662 d -> arraytype = ARRAYTYPE_ARRAY;
663 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
667 d -> arraytype = ARRAYTYPE_OBJECT;
668 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
675 /******************* Funktion: freearraydescriptor *****************************
677 entfernt eine mit buildarraydescriptor erzeugte Struktur wieder
680 *******************************************************************************/
682 static void freearraydescriptor (constant_arraydescriptor *d)
685 constant_arraydescriptor *n = d->elementdescriptor;
686 FREE (d, constant_arraydescriptor);
691 /*********************** Funktion: displayarraydescriptor *********************/
693 static void displayarraydescriptor (constant_arraydescriptor *d)
695 switch (d->arraytype) {
696 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
697 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
698 case ARRAYTYPE_CHAR: printf ("char[]"); break;
699 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
700 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
701 case ARRAYTYPE_INT: printf ("int[]"); break;
702 case ARRAYTYPE_LONG: printf ("long[]"); break;
703 case ARRAYTYPE_SHORT: printf ("short[]"); break;
704 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
705 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
711 /******************************************************************************/
712 /******************** Funktionen fuer Fields **********************************/
713 /******************************************************************************/
716 /************************ Funktion: field_load *********************************
718 l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
719 und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
720 Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
723 *******************************************************************************/
725 static void field_load (fieldinfo *f, classinfo *c)
730 f -> flags = suck_u2 (); /* ACC flags */
731 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
732 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
733 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
734 f -> offset = 0; /* offset from start of object */
737 case TYPE_INT: f->value.i = 0; break;
738 case TYPE_FLOAT: f->value.f = 0.0; break;
739 case TYPE_DOUBLE: f->value.d = 0.0; break;
740 case TYPE_ADDRESS: f->value.a = NULL;
741 heap_addreference (&(f->value.a)); /* make global reference (GC) */
745 f->value.l = 0; break;
747 f->value.l.low = 0; f->value.l.high = 0; break;
751 /* read attributes */
753 for (i=0; i<attrnum; i++) {
757 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
759 if ( aname != utf_constantvalue ) {
760 /* unknown attribute */
761 skipattributebody ();
764 /* constant value attribute */
766 /* skip attribute length */
768 /* index of value in constantpool */
771 /* initialize field with value from constantpool */
774 constant_integer *ci =
775 class_getconstant(c, pindex, CONSTANT_Integer);
776 f->value.i = ci -> value;
782 class_getconstant(c, pindex, CONSTANT_Long);
784 f->value.l = cl -> value;
790 class_getconstant(c, pindex, CONSTANT_Float);
792 f->value.f = cf->value;
797 constant_double *cd =
798 class_getconstant(c, pindex, CONSTANT_Double);
800 f->value.d = cd->value;
805 utf *u = class_getconstant(c, pindex, CONSTANT_String);
806 /* create javastring from compressed utf8-string */
807 f->value.a = literalstring_new(u);
812 log_text ("Invalid Constant - Type");
821 /********************** function: field_free **********************************/
823 static void field_free (fieldinfo *f)
829 /************** Funktion: field_display (nur zu Debug-Zwecken) ****************/
831 static void field_display (fieldinfo *f)
834 printflags (f -> flags);
836 utf_display (f -> name);
838 utf_display (f -> descriptor);
839 printf (" offset: %ld\n", (long int) (f -> offset) );
843 /******************************************************************************/
844 /************************* Funktionen f"ur Methods ****************************/
845 /******************************************************************************/
848 /*********************** Funktion: method_load *********************************
850 l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit
851 eine schon existierende 'methodinfo'-Struktur aus.
852 Bei allen native-Methoden wird au"serdem gleich der richtige
853 Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
854 Zeiger auf den Compiler
856 *******************************************************************************/
858 static void method_load (methodinfo *m, classinfo *c)
868 m -> flags = suck_u2 ();
869 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
870 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
873 m -> exceptiontable = NULL;
874 m -> entrypoint = NULL;
876 m -> stubroutine = NULL;
878 if (! (m->flags & ACC_NATIVE) ) {
879 m -> stubroutine = createcompilerstub (m);
883 functionptr f = native_findfunction
884 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
889 m -> stubroutine = createnativestub (f, m);
892 m -> stubroutine = oldcreatenativestub (f, m);
899 for (i=0; i<attrnum; i++) {
902 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
904 if ( aname != utf_code) {
905 skipattributebody ();
908 if (m -> jcode) panic ("Two code-attributes for one method!");
911 m -> maxstack = suck_u2();
912 m -> maxlocals = suck_u2();
913 m -> jcodelength = suck_u4();
914 m -> jcode = MNEW (u1, m->jcodelength);
915 suck_nbytes (m->jcode, m->jcodelength);
916 m -> exceptiontablelength = suck_u2 ();
917 m -> exceptiontable =
918 MNEW (exceptiontable, m->exceptiontablelength);
921 count_vmcode_len += m->jcodelength + 18;
922 count_extable_len += 8 * m->exceptiontablelength;
925 for (e=0; e < m->exceptiontablelength; e++) {
927 m -> exceptiontable[e].startpc = suck_u2();
928 m -> exceptiontable[e].endpc = suck_u2();
929 m -> exceptiontable[e].handlerpc = suck_u2();
932 if (!idx) m -> exceptiontable[e].catchtype = NULL;
934 m -> exceptiontable[e].catchtype =
935 class_getconstant (c, idx, CONSTANT_Class);
939 skipattributes ( suck_u2() );
946 /********************* Funktion: method_free ***********************************
948 gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
951 *******************************************************************************/
953 static void method_free (methodinfo *m)
955 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
956 if (m->exceptiontable)
957 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
958 if (m->mcode) CFREE (m->mcode, m->mcodelength);
959 if (m->stubroutine) {
960 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
961 else removecompilerstub (m->stubroutine);
966 /************** Funktion: method_display (nur zu Debug-Zwecken) **************/
968 void method_display (methodinfo *m)
971 printflags (m -> flags);
973 utf_display (m -> name);
975 utf_display (m -> descriptor);
980 /******************** Funktion: method_canoverwrite ****************************
982 "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch
983 ist (also mit einer Methodendefinition eine andere "uberschrieben
986 *******************************************************************************/
988 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
990 if (m->name != old->name) return false;
991 if (m->descriptor != old->descriptor) return false;
992 if (m->flags & ACC_STATIC) return false;
999 /******************************************************************************/
1000 /************************ Funktionen fuer Class *******************************/
1001 /******************************************************************************/
1004 /******************** function: class_getconstant ******************************
1006 retrieves the value at position 'pos' of the constantpool of a class
1007 if the type of the value is other than 'ctype' the system is stopped
1009 *******************************************************************************/
1011 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1013 /* invalid position in constantpool */
1014 if (pos >= c->cpcount)
1015 panic ("Attempt to access constant outside range");
1017 /* check type of constantpool entry */
1018 if (c->cptags[pos] != ctype) {
1019 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1020 (int) ctype, (int) c->cptags[pos] );
1024 return c->cpinfos[pos];
1028 /********************* Funktion: class_constanttype ****************************
1030 Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer
1033 *******************************************************************************/
1035 u4 class_constanttype (classinfo *c, u4 pos)
1037 if (pos >= c->cpcount)
1038 panic ("Attempt to access constant outside range");
1039 return c->cptags[pos];
1043 /******************** function: class_loadcpool ********************************
1045 loads the constantpool of a class,
1046 the entries are transformed into a simpler format
1047 by resolving references
1048 (a detailed overview of the compact structures can be found in global.h)
1050 *******************************************************************************/
1052 static void class_loadcpool (classinfo *c)
1055 /* The following structures are used to save information which cannot be
1056 processed during the first pass. After the complete constantpool has
1057 been traversed the references can be resolved.
1058 (only in specific order) */
1060 /* CONSTANT_Class_info entries */
1061 typedef struct forward_class {
1062 struct forward_class *next;
1067 /* CONSTANT_String */
1068 typedef struct forward_string {
1069 struct forward_string *next;
1074 /* CONSTANT_NameAndType */
1075 typedef struct forward_nameandtype {
1076 struct forward_nameandtype *next;
1080 } forward_nameandtype;
1082 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1083 typedef struct forward_fieldmethint {
1084 struct forward_fieldmethint *next;
1088 u2 nameandtype_index;
1089 } forward_fieldmethint;
1093 long int dumpsize = dump_size ();
1095 forward_class *forward_classes = NULL;
1096 forward_string *forward_strings = NULL;
1097 forward_nameandtype *forward_nameandtypes = NULL;
1098 forward_fieldmethint *forward_fieldmethints = NULL;
1100 /* number of entries in the constant_pool table */
1101 u4 cpcount = c -> cpcount = suck_u2();
1102 /* allocate memory */
1103 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1104 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1107 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1110 /* initialize constantpool */
1111 for (idx=0; idx<cpcount; idx++) {
1112 cptags[idx] = CONSTANT_UNUSED;
1113 cpinfos[idx] = NULL;
1117 /******* first pass *******/
1118 /* entries which cannot be resolved now are written into
1119 temporary structures and traversed again later */
1122 while (idx < cpcount) {
1123 /* get constant type */
1127 case CONSTANT_Class: {
1128 forward_class *nfc = DNEW(forward_class);
1130 nfc -> next = forward_classes;
1131 forward_classes = nfc;
1133 nfc -> thisindex = idx;
1134 /* reference to CONSTANT_NameAndType */
1135 nfc -> name_index = suck_u2 ();
1141 case CONSTANT_Fieldref:
1142 case CONSTANT_Methodref:
1143 case CONSTANT_InterfaceMethodref: {
1144 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1146 nff -> next = forward_fieldmethints;
1147 forward_fieldmethints = nff;
1149 nff -> thisindex = idx;
1152 /* class or interface type that contains the declaration of the field or method */
1153 nff -> class_index = suck_u2 ();
1154 /* name and descriptor of the field or method */
1155 nff -> nameandtype_index = suck_u2 ();
1161 case CONSTANT_String: {
1162 forward_string *nfs = DNEW (forward_string);
1164 nfs -> next = forward_strings;
1165 forward_strings = nfs;
1167 nfs -> thisindex = idx;
1168 /* reference to CONSTANT_Utf8_info with string characters */
1169 nfs -> string_index = suck_u2 ();
1175 case CONSTANT_NameAndType: {
1176 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1178 nfn -> next = forward_nameandtypes;
1179 forward_nameandtypes = nfn;
1181 nfn -> thisindex = idx;
1182 /* reference to CONSTANT_Utf8_info containing simple name */
1183 nfn -> name_index = suck_u2 ();
1184 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1185 nfn -> sig_index = suck_u2 ();
1191 case CONSTANT_Integer: {
1192 constant_integer *ci = NEW (constant_integer);
1195 count_const_pool_len += sizeof(constant_integer);
1198 ci -> value = suck_s4 ();
1199 cptags [idx] = CONSTANT_Integer;
1206 case CONSTANT_Float: {
1207 constant_float *cf = NEW (constant_float);
1210 count_const_pool_len += sizeof(constant_float);
1213 cf -> value = suck_float ();
1214 cptags [idx] = CONSTANT_Float;
1220 case CONSTANT_Long: {
1221 constant_long *cl = NEW(constant_long);
1224 count_const_pool_len += sizeof(constant_long);
1227 cl -> value = suck_s8 ();
1228 cptags [idx] = CONSTANT_Long;
1234 case CONSTANT_Double: {
1235 constant_double *cd = NEW(constant_double);
1238 count_const_pool_len += sizeof(constant_double);
1241 cd -> value = suck_double ();
1242 cptags [idx] = CONSTANT_Double;
1248 case CONSTANT_Utf8: {
1250 /* number of bytes in the bytes array (not string-length) */
1251 u4 length = suck_u2();
1252 cptags [idx] = CONSTANT_Utf8;
1253 /* insert utf-string into the utf-symboltable */
1254 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1255 /* skip bytes of the string */
1256 skip_nbytes(length);
1262 sprintf (logtext, "Unkown constant type: %d",(int) t);
1271 /* resolve entries in temporary structures */
1273 while (forward_classes) {
1275 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1277 if ( (name->blength>0) && (name->text[0]=='[') ) {
1278 /* check validity of descriptor */
1279 checkfielddescriptor (name->text, utf_end(name));
1281 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1282 cpinfos [forward_classes -> thisindex] =
1283 buildarraydescriptor(name->text, name->blength);
1287 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1288 /* retrieve class from class-table */
1289 cpinfos [forward_classes -> thisindex] = class_new (name);
1291 forward_classes = forward_classes -> next;
1295 while (forward_strings) {
1297 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1299 /* resolve utf-string */
1300 cptags [forward_strings -> thisindex] = CONSTANT_String;
1301 cpinfos [forward_strings -> thisindex] = text;
1303 forward_strings = forward_strings -> next;
1306 while (forward_nameandtypes) {
1307 constant_nameandtype *cn = NEW (constant_nameandtype);
1310 count_const_pool_len += sizeof(constant_nameandtype);
1313 /* resolve simple name and descriptor */
1314 cn -> name = class_getconstant
1315 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1316 cn -> descriptor = class_getconstant
1317 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1319 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1320 cpinfos [forward_nameandtypes -> thisindex] = cn;
1322 forward_nameandtypes = forward_nameandtypes -> next;
1326 while (forward_fieldmethints) {
1327 constant_nameandtype *nat;
1328 constant_FMIref *fmi = NEW (constant_FMIref);
1331 count_const_pool_len += sizeof(constant_FMIref);
1333 /* resolve simple name and descriptor */
1334 nat = class_getconstant
1335 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1337 fmi -> class = class_getconstant
1338 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1339 fmi -> name = nat -> name;
1340 fmi -> descriptor = nat -> descriptor;
1342 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1343 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1345 switch (forward_fieldmethints -> tag) {
1346 case CONSTANT_Fieldref: /* check validity of descriptor */
1347 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1349 case CONSTANT_InterfaceMethodref:
1350 case CONSTANT_Methodref: /* check validity of descriptor */
1351 checkmethoddescriptor (fmi->descriptor);
1355 forward_fieldmethints = forward_fieldmethints -> next;
1360 dump_release (dumpsize);
1364 /********************** Funktion: class_load ***********************************
1366 l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
1367 'classinfo'-Struktur mu"s bereits angelegt worden sein.
1369 Die Superklasse und die Interfaces, die diese Klasse implementiert,
1370 m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die
1371 Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
1373 Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
1374 und in die Liste 'unlinkedclasses' eingh"angt.
1376 *******************************************************************************/
1378 static int class_load (classinfo *c)
1383 /* output for debugging purposes */
1385 sprintf (logtext, "Loading class: ");
1386 utf_sprint (logtext+strlen(logtext), c->name );
1390 /* load classdata, throw exception on error */
1391 if (!suck_start (c->name)) {
1392 throw_classnotfoundexception();
1396 /* check signature */
1397 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1401 if (ma != MAJOR_VERSION) {
1402 sprintf (logtext, "Can only support major version %d, but not %d",
1403 MAJOR_VERSION, (int) ma);
1406 if (mi > MINOR_VERSION) {
1407 sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
1412 class_loadcpool (c);
1415 c -> flags = suck_u2 ();
1419 /* retrieve superclass */
1420 if ( (i = suck_u2 () ) ) {
1421 c -> super = class_getconstant (c, i, CONSTANT_Class);
1427 /* retrieve interfaces */
1428 c -> interfacescount = suck_u2 ();
1429 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1430 for (i=0; i < c -> interfacescount; i++) {
1431 c -> interfaces [i] =
1432 class_getconstant (c, suck_u2(), CONSTANT_Class);
1436 c -> fieldscount = suck_u2 ();
1437 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1438 for (i=0; i < c -> fieldscount; i++) {
1439 field_load (&(c->fields[i]), c);
1443 c -> methodscount = suck_u2 ();
1444 c -> methods = MNEW (methodinfo, c -> methodscount);
1445 for (i=0; i < c -> methodscount; i++) {
1446 method_load (&(c -> methods [i]), c);
1450 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1451 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1452 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1455 /* load variable-length attribute structures */
1456 attribute_load (suck_u2(), c);
1461 /* remove class from list of unloaded classes and
1462 add to list of unlinked classes */
1463 list_remove (&unloadedclasses, c);
1464 list_addlast (&unlinkedclasses, c);
1471 /************** interne Funktion: class_highestinterface ***********************
1473 wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
1474 die Interfacetable einer Klasse sein mu"s.
1476 *******************************************************************************/
1478 static s4 class_highestinterface (classinfo *c)
1483 if ( ! (c->flags & ACC_INTERFACE) ) {
1484 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1485 utf_sprint (logtext+strlen(logtext), c->name);
1490 for (i=0; i<c->interfacescount; i++) {
1491 s4 h2 = class_highestinterface (c->interfaces[i]);
1498 /* class_addinterface **********************************************************
1500 wird von der Funktion class_link ben"otigt, um eine Virtual Function
1501 Table f"ur ein Interface (und alle weiteren von diesem Interface
1502 implementierten Interfaces) in eine Klasse einzutragen.
1504 *******************************************************************************/
1506 static void class_addinterface (classinfo *c, classinfo *ic)
1510 vftbl *vftbl = c->vftbl;
1512 if (i >= vftbl->interfacetablelength)
1513 panic ("Inernal error: interfacetable overflow");
1514 if (vftbl->interfacetable[-i])
1517 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1518 vftbl->interfacevftbllength[i] = 1;
1519 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1520 vftbl->interfacetable[-i][0] = NULL;
1523 vftbl->interfacevftbllength[i] = ic->methodscount;
1524 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1527 count_vftbl_len += sizeof(methodptr) *
1528 (ic->methodscount + (ic->methodscount == 0));
1531 for (j=0; j<ic->methodscount; j++) {
1534 for (m = 0; m < sc->methodscount; m++) {
1535 methodinfo *mi = &(sc->methods[m]);
1536 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1537 vftbl->interfacetable[-i][j] =
1538 vftbl->table[mi->vftblindex];
1548 for (j = 0; j < ic->interfacescount; j++)
1549 class_addinterface(c, ic->interfaces[j]);
1553 /********************** Funktion: class_link ***********************************
1555 versucht, eine Klasse in das System voll zu integrieren (linken). Dazu
1556 m"ussen sowol die Superklasse, als auch alle implementierten
1557 Interfaces schon gelinkt sein.
1558 Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz
1559 dieser Klasse, als auch die Virtual Function Tables f"ur normale
1560 Methoden als auch Interface-Methoden.
1562 Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
1563 der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
1565 Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
1567 Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
1568 eine Endlosschleife!! (Da muss ich mir noch was einfallen lassen)
1570 *******************************************************************************/
1572 static void class_link (classinfo *c)
1574 s4 supervftbllength; /* vftbllegnth of super class */
1575 s4 vftbllength; /* vftbllength of current class */
1576 s4 interfacetablelength; /* interface table length */
1577 classinfo *super = c->super; /* super class */
1578 classinfo *ic, *c2; /* intermediate class variables */
1579 vftbl *v; /* vftbl of current class */
1580 s4 i; /* interface/method/field counter */
1583 /* check if all superclasses are already linked, if not put c at end of
1584 unlinked list and return. Additionally initialize class fields. */
1586 /* check interfaces */
1588 for (i = 0; i < c->interfacescount; i++) {
1589 ic = c->interfaces[i];
1591 list_remove(&unlinkedclasses, c);
1592 list_addlast(&unlinkedclasses, c);
1597 /* check super class */
1599 if (super == NULL) { /* class java.long.Object */
1601 c->instancesize = sizeof(java_objectheader);
1603 vftbllength = supervftbllength = 0;
1605 c->finalizer = NULL;
1608 if (!super->linked) {
1609 list_remove(&unlinkedclasses, c);
1610 list_addlast(&unlinkedclasses, c);
1614 if (c->flags & ACC_INTERFACE)
1615 c->index = interfaceindex++;
1617 c->index = super->index + 1;
1619 c->instancesize = super->instancesize;
1621 vftbllength = supervftbllength = super->vftbl->vftbllength;
1623 c->finalizer = super->finalizer;
1628 sprintf (logtext, "Linking Class: ");
1629 utf_sprint (logtext+strlen(logtext), c->name );
1633 /* compute vftbl length */
1635 for (i = 0; i < c->methodscount; i++) {
1636 methodinfo *m = &(c->methods[i]);
1638 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1639 classinfo *sc = super;
1642 for (j = 0; j < sc->methodscount; j++) {
1643 if (method_canoverwrite(m, &(sc->methods[j]))) {
1644 m->vftblindex = sc->methods[j].vftblindex;
1645 goto foundvftblindex;
1650 m->vftblindex = (vftbllength++);
1656 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1659 /* compute interfacetable length */
1661 interfacetablelength = 0;
1664 for (i = 0; i < c2->interfacescount; i++) {
1665 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1666 if (h > interfacetablelength)
1667 interfacetablelength = h;
1672 /* allocate virtual function table */
1674 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1675 (vftbllength - 1) + sizeof(methodptr*) *
1676 (interfacetablelength - (interfacetablelength > 0)));
1677 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1678 (interfacetablelength > 1));
1679 c->header.vftbl = c->vftbl = v;
1681 v->vftbllength = vftbllength;
1682 v->interfacetablelength = interfacetablelength;
1684 /* copy virtual function table of super class */
1686 for (i = 0; i < supervftbllength; i++)
1687 v->table[i] = super->vftbl->table[i];
1689 /* add method stubs into virtual function table */
1691 for (i = 0; i < c->methodscount; i++) {
1692 methodinfo *m = &(c->methods[i]);
1693 if (!(m->flags & ACC_STATIC)) {
1694 v->table[m->vftblindex] = m->stubroutine;
1698 /* compute instance size and offset of each field */
1700 for (i = 0; i < c->fieldscount; i++) {
1702 fieldinfo *f = &(c->fields[i]);
1704 if (!(f->flags & ACC_STATIC) ) {
1705 dsize = desc_typesize (f->descriptor);
1706 c->instancesize = ALIGN (c->instancesize, dsize);
1707 f->offset = c->instancesize;
1708 c->instancesize += dsize;
1712 /* initialize interfacetable and interfacevftbllength */
1714 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1717 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1720 for (i = 0; i < interfacetablelength; i++) {
1721 v->interfacevftbllength[i] = 0;
1722 v->interfacetable[-i] = NULL;
1725 /* add interfaces */
1727 for (c2 = c; c2 != NULL; c2 = c2->super)
1728 for (i = 0; i < c2->interfacescount; i++) {
1729 class_addinterface (c, c2->interfaces[i]);
1732 /* add finalizer method (not for java.lang.Object) */
1734 if (super != NULL) {
1736 static utf *finame = NULL;
1737 static utf *fidesc = NULL;
1740 finame = utf_finalize;
1742 fidesc = utf_fidesc;
1744 fi = class_findmethod (c, finame, fidesc);
1746 if (!(fi->flags & ACC_STATIC)) {
1756 list_remove (&unlinkedclasses, c);
1757 list_addlast (&linkedclasses, c);
1761 /******************* Funktion: class_freepool **********************************
1763 Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
1766 *******************************************************************************/
1768 static void class_freecpool (classinfo *c)
1774 for (idx=0; idx < c->cpcount; idx++) {
1775 tag = c->cptags[idx];
1776 info = c->cpinfos[idx];
1780 case CONSTANT_Fieldref:
1781 case CONSTANT_Methodref:
1782 case CONSTANT_InterfaceMethodref:
1783 FREE (info, constant_FMIref);
1785 case CONSTANT_Integer:
1786 FREE (info, constant_integer);
1788 case CONSTANT_Float:
1789 FREE (info, constant_float);
1792 FREE (info, constant_long);
1794 case CONSTANT_Double:
1795 FREE (info, constant_double);
1797 case CONSTANT_NameAndType:
1798 FREE (info, constant_nameandtype);
1800 case CONSTANT_Arraydescriptor:
1801 freearraydescriptor (info);
1807 MFREE (c -> cptags, u1, c -> cpcount);
1808 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1812 /*********************** Funktion: class_free **********************************
1814 Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
1816 *******************************************************************************/
1818 static void class_free (classinfo *c)
1823 class_freecpool (c);
1825 MFREE (c->interfaces, classinfo*, c->interfacescount);
1827 for (i = 0; i < c->fieldscount; i++)
1828 field_free(&(c->fields[i]));
1829 MFREE (c->fields, fieldinfo, c->fieldscount);
1831 for (i = 0; i < c->methodscount; i++)
1832 method_free(&(c->methods[i]));
1833 MFREE (c->methods, methodinfo, c->methodscount);
1835 if ((v = c->vftbl) != NULL) {
1836 for (i = 0; i < v->interfacetablelength; i++) {
1837 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1839 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1841 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1842 sizeof(methodptr*) * (v->interfacetablelength -
1843 (v->interfacetablelength > 0));
1844 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1845 (v->interfacetablelength > 1));
1849 if (c->innerclasscount)
1850 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1852 FREE (c, classinfo);
1855 /************************* Funktion: class_findfield ***************************
1857 sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
1860 *******************************************************************************/
1863 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1867 for (i = 0; i < c->fieldscount; i++) {
1868 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1869 return &(c->fields[i]);
1872 panic ("Can not find field given in CONSTANT_Fieldref");
1877 /************************* Funktion: class_findmethod **************************
1879 sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1881 Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1883 *******************************************************************************/
1885 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1888 for (i = 0; i < c->methodscount; i++) {
1889 if ((c->methods[i].name == name) && ((desc == NULL) ||
1890 (c->methods[i].descriptor == desc)))
1891 return &(c->methods[i]);
1896 /************************* Funktion: class_findmethod_approx ******************
1898 sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1900 Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1901 beim Vergleichen des Descriptors wird der R"uckgabewert nicht betrachtet
1903 *******************************************************************************/
1905 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1909 for (i = 0; i < c->methodscount; i++)
1910 if (c->methods[i].name == name) {
1911 utf *meth_descr = c->methods[i].descriptor;
1915 return &(c->methods[i]);
1917 if (desc->blength <= meth_descr->blength) {
1918 /* current position in utf text */
1919 char *desc_utf_ptr = desc->text;
1920 char *meth_utf_ptr = meth_descr->text;
1921 /* points behind utf strings */
1922 char *desc_end = utf_end(desc);
1923 char *meth_end = utf_end(meth_descr);
1926 /* compare argument types */
1927 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1929 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1930 break; /* no match */
1933 return &(c->methods[i]); /* all parameter types equal */
1941 /***************** Funktion: class_resolvemethod_approx ***********************
1943 sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1944 (ohne Beachtung des R"uckgabewertes)
1946 *******************************************************************************/
1948 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1951 /* search for method (ignore returntype) */
1952 methodinfo *m = class_findmethod_approx (c, name, desc);
1955 /* search superclass */
1962 /************************* Funktion: class_resolvemethod ***********************
1964 sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1966 *******************************************************************************/
1969 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
1972 methodinfo *m = class_findmethod (c, name, desc);
1974 /* search superclass */
1982 /************************* Funktion: class_issubclass **************************
1984 "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.
1986 *******************************************************************************/
1988 bool class_issubclass (classinfo *sub, classinfo *super)
1991 if (!sub) return false;
1992 if (sub==super) return true;
1999 /****************** Initialisierungsfunktion f"ur eine Klasse ******************
2001 In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
2002 Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
2003 Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
2006 *******************************************************************************/
2009 extern int blockInts;
2012 void class_init (classinfo *c)
2015 java_objectheader *exceptionptr;
2019 if (!makeinitializations) return;
2020 if (c->initialized) return;
2021 c -> initialized = true;
2023 if (c->super) class_init (c->super);
2024 for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
2026 m = class_findmethod (c,
2031 sprintf (logtext, "Class ");
2032 utf_sprint (logtext+strlen(logtext), c->name);
2033 sprintf (logtext+strlen(logtext), " has no initializer");
2039 if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
2042 sprintf (logtext, "Starting initializer for class: ");
2043 utf_sprint (logtext+strlen(logtext), c->name);
2052 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2055 assert(blockInts == 0);
2060 printf ("#### Initializer of ");
2061 utf_display (c->name);
2062 printf (" has thrown: ");
2063 utf_display (exceptionptr->vftbl->class->name);
2069 sprintf (logtext, "Finished initializer for class: ");
2070 utf_sprint (logtext+strlen(logtext), c->name);
2074 if (c->name == utf_systemclass) {
2075 /* class java.lang.System requires explicit initialization */
2078 printf ("#### Initializing class System");
2080 /* find initializing method */
2081 m = class_findmethod (c,
2082 utf_initsystemclass,
2086 /* no method found */
2087 log("initializeSystemClass failed");
2096 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2099 assert(blockInts == 0);
2104 printf ("#### initializeSystemClass has thrown: ");
2105 utf_display (exceptionptr->vftbl->class->name);
2115 /********* Funktion: class_showconstantpool (nur f"ur Debug-Zwecke) *********/
2117 void class_showconstantpool (classinfo *c)
2122 printf ("---- dump of constant pool ----\n");
2124 for (i=0; i<c->cpcount; i++) {
2125 printf ("#%d: ", (int) i);
2127 e = c -> cpinfos [i];
2130 switch (c -> cptags [i]) {
2131 case CONSTANT_Class:
2132 printf ("Classreference -> ");
2133 utf_display ( ((classinfo*)e) -> name );
2136 case CONSTANT_Fieldref:
2137 printf ("Fieldref -> "); goto displayFMI;
2138 case CONSTANT_Methodref:
2139 printf ("Methodref -> "); goto displayFMI;
2140 case CONSTANT_InterfaceMethodref:
2141 printf ("InterfaceMethod -> "); goto displayFMI;
2144 constant_FMIref *fmi = e;
2145 utf_display ( fmi->class->name );
2147 utf_display ( fmi->name);
2149 utf_display ( fmi->descriptor );
2153 case CONSTANT_String:
2154 printf ("String -> ");
2157 case CONSTANT_Integer:
2158 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2160 case CONSTANT_Float:
2161 printf ("Float -> %f", ((constant_float*)e) -> value);
2163 case CONSTANT_Double:
2164 printf ("Double -> %f", ((constant_double*)e) -> value);
2168 u8 v = ((constant_long*)e) -> value;
2170 printf ("Long -> %ld", (long int) v);
2172 printf ("Long -> HI: %ld, LO: %ld\n",
2173 (long int) v.high, (long int) v.low);
2177 case CONSTANT_NameAndType:
2178 { constant_nameandtype *cnt = e;
2179 printf ("NameAndType: ");
2180 utf_display (cnt->name);
2182 utf_display (cnt->descriptor);
2186 printf ("Utf8 -> ");
2189 case CONSTANT_Arraydescriptor: {
2190 printf ("Arraydescriptor: ");
2191 displayarraydescriptor (e);
2195 panic ("Invalid type of ConstantPool-Entry");
2207 /********** Funktion: class_showmethods (nur f"ur Debug-Zwecke) *************/
2209 void class_showmethods (classinfo *c)
2213 printf ("--------- Fields and Methods ----------------\n");
2214 printf ("Flags: "); printflags (c->flags); printf ("\n");
2216 printf ("This: "); utf_display (c->name); printf ("\n");
2218 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2220 printf ("Index: %d\n", c->index);
2222 printf ("interfaces:\n");
2223 for (i=0; i < c-> interfacescount; i++) {
2225 utf_display (c -> interfaces[i] -> name);
2226 printf (" (%d)\n", c->interfaces[i] -> index);
2229 printf ("fields:\n");
2230 for (i=0; i < c -> fieldscount; i++) {
2231 field_display (&(c -> fields[i]));
2234 printf ("methods:\n");
2235 for (i=0; i < c -> methodscount; i++) {
2236 methodinfo *m = &(c->methods[i]);
2237 if ( !(m->flags & ACC_STATIC))
2238 printf ("vftblindex: %d ", m->vftblindex);
2240 method_display ( m );
2244 printf ("Virtual function table:\n");
2245 for (i=0; i<c->vftbl->vftbllength; i++) {
2246 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2253 /******************************************************************************/
2254 /******************* Funktionen fuer den Class-loader generell ****************/
2255 /******************************************************************************/
2258 /********************* Funktion: loader_load ***********************************
2260 l"adt und linkt die ge"unschte Klasse und alle davon
2261 referenzierten Klassen und Interfaces
2262 Return: Einen Zeiger auf diese Klasse
2264 *******************************************************************************/
2266 classinfo *loader_load (utf *topname)
2270 long int starttime=0,stoptime=0;
2272 intsDisable(); /* schani */
2274 if (getloadingtime) starttime = getcputime();
2276 top = class_new (topname);
2279 while ( (c = list_first(&unloadedclasses)) ) {
2280 if (!class_load (c)) {
2281 list_remove (&unloadedclasses, c);
2287 while ( (c = list_first(&unlinkedclasses)) ) {
2292 if (getloadingtime) {
2293 stoptime = getcputime();
2294 loadingtime += (stoptime-starttime);
2297 intsRestore(); /* schani */
2303 /**************** function: create_primitive_classes ***************************
2305 create classes representing primitive types
2307 ********************************************************************************/
2310 void create_primitive_classes()
2314 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2315 /* create primitive class */
2316 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2318 /* prevent loader from loading primitive class */
2319 list_remove (&unloadedclasses, c);
2320 /* add to unlinked classes */
2321 list_addlast (&unlinkedclasses, c);
2322 c -> super = class_java_lang_Object;
2325 primitivetype_table[i].class_primitive = c;
2327 /* create class for wrapping the primitive type */
2328 primitivetype_table[i].class_wrap =
2329 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2333 /***************** function: create_array_class ********************************
2335 create class representing an array
2337 ********************************************************************************/
2340 classinfo *create_array_class(utf *u)
2342 classinfo *c = class_new (u);
2343 /* prevent loader from loading the array class */
2344 list_remove (&unloadedclasses, c);
2345 /* add to unlinked classes */
2346 list_addlast (&unlinkedclasses, c);
2347 c -> super = class_java_lang_Object;
2353 /********************** Funktion: loader_init **********************************
2355 Initialisiert alle Listen und l"adt alle Klassen, die vom System
2356 und vom Compiler direkt ben"otigt werden.
2358 *******************************************************************************/
2365 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2366 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2367 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2369 /* create utf-symbols for pointer comparison of frequently used strings */
2370 utf_innerclasses = utf_new_char("InnerClasses");
2371 utf_constantvalue = utf_new_char("ConstantValue");
2372 utf_code = utf_new_char("Code");
2373 utf_finalize = utf_new_char("finalize");
2374 utf_fidesc = utf_new_char("()V");
2375 utf_clinit = utf_new_char("<clinit>");
2376 utf_initsystemclass = utf_new_char("initializeSystemClass");
2377 utf_systemclass = utf_new_char("java/lang/System");
2379 /* create class for arrays */
2380 class_array = class_new ( utf_new_char ("The_Array_Class") );
2381 list_remove (&unloadedclasses, class_array);
2383 /* create class for strings, load it after class Object was loaded */
2384 string_class = utf_new_char ("java/lang/String");
2385 class_java_lang_String = class_new(string_class);
2386 list_remove (&unloadedclasses, class_java_lang_String);
2388 class_java_lang_Object =
2389 loader_load ( utf_new_char ("java/lang/Object") );
2391 list_addlast(&unloadedclasses, class_java_lang_String);
2393 class_java_lang_String =
2394 loader_load ( string_class );
2395 class_java_lang_ClassCastException =
2396 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2397 class_java_lang_NullPointerException =
2398 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2399 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2400 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2401 class_java_lang_NegativeArraySizeException = loader_load (
2402 utf_new_char ("java/lang/NegativeArraySizeException") );
2403 class_java_lang_OutOfMemoryError = loader_load (
2404 utf_new_char ("java/lang/OutOfMemoryError") );
2405 class_java_lang_ArrayStoreException =
2406 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2407 class_java_lang_ArithmeticException =
2408 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2409 class_java_lang_ThreadDeath = /* schani */
2410 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2412 /* link class for arrays */
2413 list_addlast (&unlinkedclasses, class_array);
2414 class_array -> super = class_java_lang_Object;
2415 class_link (class_array);
2417 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2418 stringtable_update();
2420 /* create classes representing primitive types */
2421 create_primitive_classes();
2423 proto_java_lang_ClassCastException =
2424 builtin_new(class_java_lang_ClassCastException);
2425 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2427 proto_java_lang_NullPointerException =
2428 builtin_new(class_java_lang_NullPointerException);
2429 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2431 proto_java_lang_ArrayIndexOutOfBoundsException =
2432 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2433 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2435 proto_java_lang_NegativeArraySizeException =
2436 builtin_new(class_java_lang_NegativeArraySizeException);
2437 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2439 proto_java_lang_OutOfMemoryError =
2440 builtin_new(class_java_lang_OutOfMemoryError);
2441 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2443 proto_java_lang_ArithmeticException =
2444 builtin_new(class_java_lang_ArithmeticException);
2445 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2447 proto_java_lang_ArrayStoreException =
2448 builtin_new(class_java_lang_ArrayStoreException);
2449 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2451 proto_java_lang_ThreadDeath = /* schani */
2452 builtin_new(class_java_lang_ThreadDeath);
2453 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2459 /********************* Funktion: loader_initclasses ****************************
2461 initialisiert alle geladenen aber noch nicht initialisierten Klassen
2463 *******************************************************************************/
2465 void loader_initclasses ()
2469 intsDisable(); /* schani */
2471 if (makeinitializations) {
2472 c = list_first (&linkedclasses);
2475 c = list_next (&linkedclasses, c);
2479 intsRestore(); /* schani */
2482 static s4 classvalue = 0;
2484 static void loader_compute_class_values (classinfo *c)
2488 c->vftbl->baseval = ++classvalue;
2490 while (subs != NULL) {
2491 loader_compute_class_values(subs);
2492 subs = subs->nextsub;
2494 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2498 for (i = 0; i < c->index; i++)
2500 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2501 utf_display(c->name);
2508 void loader_compute_subclasses ()
2512 intsDisable(); /* schani */
2514 c = list_first (&linkedclasses);
2516 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2517 c->nextsub = c->super->sub;
2520 c = list_next (&linkedclasses, c);
2523 loader_compute_class_values(class_java_lang_Object);
2525 intsRestore(); /* schani */
2530 /******************** function: classloader_buffer ***************************
2532 set buffer for reading classdata
2534 ******************************************************************************/
2536 void classload_buffer(u1 *buf,int len)
2539 classbuffer_size = len;
2540 classbuf_pos = buf-1;
2543 /******************** Funktion: loader_close ***********************************
2545 gibt alle Resourcen wieder frei
2547 *******************************************************************************/
2549 void loader_close ()
2553 while ( (c=list_first(&unloadedclasses)) ) {
2554 list_remove (&unloadedclasses,c);
2557 while ( (c=list_first(&unlinkedclasses)) ) {
2558 list_remove (&unlinkedclasses,c);
2561 while ( (c=list_first(&linkedclasses)) ) {
2562 list_remove (&linkedclasses,c);
2569 * These are local overrides for various environment variables in Emacs.
2570 * Please do not remove this and leave it at the end of the file, where
2571 * Emacs will automagically detect them.
2572 * ---------------------------------------------------------------------
2575 * indent-tabs-mode: t