1 /* loader.c - class loader functions
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
29 Changes: Andreas Krall
33 $Id: loader.c 593 2003-11-09 19:50:55Z twisti $
48 #include "toolbox/memory.h"
49 #include "toolbox/loging.h"
50 #include "threads/thread.h"
53 /* global variables ***********************************************************/
55 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
56 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
57 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
59 int count_class_infos = 0; /* variables for measurements */
60 int count_const_pool_len = 0;
61 int count_vftbl_len = 0;
62 int count_all_methods = 0;
63 int count_vmcode_len = 0;
64 int count_extable_len = 0;
65 int count_class_loads = 0;
66 int count_class_inits = 0;
68 bool loadverbose = false; /* switches for debug messages */
69 bool linkverbose = false;
70 bool initverbose = false;
72 bool makeinitializations = true;
74 bool getloadingtime = false; /* to measure the runtime */
75 long int loadingtime = 0;
77 static s4 interfaceindex; /* sequential numbering of interfaces */
79 list unloadedclasses; /* list of all referenced but not loaded classes */
80 list unlinkedclasses; /* list of all loaded but not linked classes */
81 list linkedclasses; /* list of all completely linked classes */
84 /* utf-symbols for pointer comparison of frequently used strings */
86 static utf *utf_innerclasses; /* InnerClasses */
87 static utf *utf_constantvalue; /* ConstantValue */
88 static utf *utf_code; /* Code */
89 static utf *utf_finalize; /* finalize */
90 static utf *utf_fidesc; /* ()V */
91 static utf *utf_clinit; /* <clinit> */
92 static utf *utf_initsystemclass; /* initializeSystemClass */
93 static utf *utf_systemclass; /* java/lang/System */
96 /* important system classes ***************************************************/
98 classinfo *class_java_lang_Object;
99 classinfo *class_java_lang_String;
100 classinfo *class_array = NULL;
103 /* These are made static so they cannot be used for throwing in native */
105 static classinfo *class_java_lang_ClassCastException;
106 static classinfo *class_java_lang_NullPointerException;
107 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
108 static classinfo *class_java_lang_NegativeArraySizeException;
109 static classinfo *class_java_lang_OutOfMemoryError;
110 static classinfo *class_java_lang_ArithmeticException;
111 static classinfo *class_java_lang_ArrayStoreException;
112 static classinfo *class_java_lang_ThreadDeath;
115 /******************************************************************************
117 structure for primitive classes: contains the class for wrapping the
118 primitive type, the primitive class, the name of the class for wrapping,
119 the one character type signature and the name of the primitive class
121 ******************************************************************************/
123 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
124 { NULL, NULL, "java/lang/Integer", 'I', "int" },
125 { NULL, NULL, "java/lang/Long", 'J', "long" },
126 { NULL, NULL, "java/lang/Float", 'F', "float" },
127 { NULL, NULL, "java/lang/Double", 'D', "double" },
128 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
129 { NULL, NULL, "java/lang/Character", 'C', "char" },
130 { NULL, NULL, "java/lang/Short", 'S', "short" },
131 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
132 { NULL, NULL, "java/lang/Void", 'V', "void" }
136 /* instances of important system classes **************************************/
138 java_objectheader *proto_java_lang_ClassCastException;
139 java_objectheader *proto_java_lang_NullPointerException;
140 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
141 java_objectheader *proto_java_lang_NegativeArraySizeException;
142 java_objectheader *proto_java_lang_OutOfMemoryError;
143 java_objectheader *proto_java_lang_ArithmeticException;
144 java_objectheader *proto_java_lang_ArrayStoreException;
145 java_objectheader *proto_java_lang_ThreadDeath;
148 /************* functions for reading classdata *********************************
150 getting classdata in blocks of variable size
151 (8,16,32,64-bit integer or float)
153 *******************************************************************************/
155 static char *classpath = ""; /* searchpath for classfiles */
156 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
157 static u1 *classbuf_pos; /* current position in classfile buffer */
158 static int classbuffer_size; /* size of classfile-data */
160 /* transfer block of classfile data into a buffer */
162 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
165 /* skip block of classfile data */
167 #define skip_nbytes(len) classbuf_pos+=len;
171 return *++classbuf_pos;
175 u1 a=suck_u1(), b=suck_u1();
176 return ((u2)a<<8)+(u2)b;
180 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
181 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
183 #define suck_s8() (s8) suck_u8()
184 #define suck_s2() (s2) suck_u2()
185 #define suck_s4() (s4) suck_u4()
186 #define suck_s1() (s1) suck_u1()
189 /* get u8 from classfile data */
197 return (hi<<32) + lo;
206 /* get float from classfile data */
208 static float suck_float ()
215 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
216 memcpy ( (u1*) (&f), buffer, 4);
218 suck_nbytes ( (u1*) (&f), 4 );
221 PANICIF (sizeof(float) != 4, "Incompatible float-format");
226 /* get double from classfile data */
227 static double suck_double ()
234 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
235 memcpy ( (u1*) (&d), buffer, 8);
237 suck_nbytes ( (u1*) (&d), 8 );
240 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
245 /************************** function suck_init *********************************
247 called once at startup, sets the searchpath for the classfiles
249 *******************************************************************************/
251 void suck_init (char *cpath)
258 /************************** function suck_start ********************************
260 returns true if classbuffer is already loaded or a file for the
261 specified class has succussfully been read in. All directories of
262 the searchpath are used to find the classfile (<classname>.class).
263 Returns false if no classfile is found and writes an error message.
265 *******************************************************************************/
268 bool suck_start (utf *classname) {
270 #define MAXFILENAME 1000 /* maximum length of a filename */
272 char filename[MAXFILENAME+10]; /* room for '.class' */
273 char *pathpos; /* position in searchpath */
274 char c, *utf_ptr; /* pointer to the next utf8-character */
276 int filenamelen, err;
279 if (classbuffer) /* classbuffer is already valid */
286 /* skip path separator */
288 while (*pathpos == ':')
291 /* extract directory from searchpath */
294 while ((*pathpos) && (*pathpos!=':')) {
295 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
296 filename[filenamelen++] = *(pathpos++);
299 filename[filenamelen++] = '/';
301 /* add classname to filename */
303 utf_ptr = classname->text;
304 while (utf_ptr < utf_end(classname)) {
305 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
307 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
309 filename[filenamelen++] = c;
314 strcpy (filename+filenamelen, ".class");
316 classfile = fopen(filename, "r");
317 if (classfile) { /* file exists */
319 /* determine size of classfile */
321 err = stat (filename, &buffer);
323 if (!err) { /* read classfile data */
324 classbuffer_size = buffer.st_size;
325 classbuffer = MNEW(u1, classbuffer_size);
326 classbuf_pos = classbuffer-1;
327 fread(classbuffer, 1, classbuffer_size, classfile);
335 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
343 /************************** function suck_stop *********************************
345 frees memory for buffer with classfile data.
346 Caution: this function may only be called if buffer has been allocated
347 by suck_start with reading a file
349 *******************************************************************************/
353 /* determine amount of classdata not retrieved by suck-operations */
355 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
357 if (classdata_left > 0) {
359 sprintf (logtext,"There are %d access bytes at end of classfile",
366 MFREE(classbuffer, u1, classbuffer_size);
370 /******************************************************************************/
371 /******************* Some support functions ***********************************/
372 /******************************************************************************/
376 void fprintflags (FILE *fp, u2 f)
378 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
379 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
380 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
381 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
382 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
383 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
384 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
385 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
386 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
387 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
388 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
391 /********** internal function: printflags (only for debugging) ***************/
392 void printflags (u2 f)
394 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
395 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
396 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
397 if ( f & ACC_STATIC ) printf (" STATIC");
398 if ( f & ACC_FINAL ) printf (" FINAL");
399 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
400 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
401 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
402 if ( f & ACC_NATIVE ) printf (" NATIVE");
403 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
404 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
408 /************************* Function: skipattribute *****************************
410 skips a (1) 'attribute' structure in the class file
412 *******************************************************************************/
414 static void skipattribute ()
417 skip_nbytes(suck_u4());
420 /********************** Function: skipattributebody ****************************
422 skips an attribute after the 16 bit reference to attribute_name has already
425 *******************************************************************************/
427 static void skipattributebody ()
429 skip_nbytes(suck_u4());
432 /************************* Function: skipattributes ****************************
434 skips num attribute structures
436 *******************************************************************************/
438 static void skipattributes (u4 num)
441 for (i = 0; i < num; i++)
445 /******************** function: innerclass_getconstant ************************
447 like class_getconstant, but if cptags is ZERO null is returned
449 *******************************************************************************/
451 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
453 /* invalid position in constantpool */
454 if (pos >= c->cpcount)
455 panic ("Attempt to access constant outside range");
457 /* constantpool entry of type 0 */
461 /* check type of constantpool entry */
462 if (c->cptags[pos] != ctype) {
463 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
464 (int) ctype, (int) c->cptags[pos] );
468 return c->cpinfos[pos];
471 /************************ function: attribute_load ****************************
473 read attributes from classfile
475 *******************************************************************************/
477 static void attribute_load (u4 num, classinfo *c)
481 for (i = 0; i < num; i++) {
482 /* retrieve attribute name */
483 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
485 if ( aname == utf_innerclasses) {
486 /* innerclasses attribute */
488 /* skip attribute length */
490 /* number of records */
491 c->innerclasscount = suck_u2();
492 /* allocate memory for innerclass structure */
493 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
495 for (j=0;j<c->innerclasscount;j++) {
497 /* The innerclass structure contains a class with an encoded name,
498 its defining scope, its simple name and a bitmask of the access flags.
499 If an inner class is not a member, its outer_class is NULL,
500 if a class is anonymous, its name is NULL. */
502 innerclassinfo *info = c->innerclass + j;
504 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
505 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
506 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
507 info->flags = suck_u2 (); /* access_flags bitmask */
510 /* unknown attribute */
511 skipattributebody ();
516 /******************* function: checkfielddescriptor ****************************
518 checks whether a field-descriptor is valid and aborts otherwise
519 all referenced classes are inserted into the list of unloaded classes
521 *******************************************************************************/
523 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
525 char *tstart; /* pointer to start of classname */
528 switch (*utf_ptr++) {
541 /* save start of classname */
544 /* determine length of classname */
545 while ( *utf_ptr++ != ';' )
546 if (utf_ptr>=end_pos)
547 panic ("Missing ';' in objecttype-descriptor");
549 /* cause loading of referenced class */
550 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
555 while ((ch = *utf_ptr++)=='[')
558 /* component type of array */
572 /* save start of classname */
575 /* determine length of classname */
576 while ( *utf_ptr++ != ';' )
577 if (utf_ptr>=end_pos)
578 panic ("Missing ';' in objecttype-descriptor");
580 /* cause loading of referenced class */
581 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
585 panic ("Ill formed methodtype-descriptor");
590 panic ("Ill formed methodtype-descriptor");
593 /* exceeding characters */
594 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
598 /******************* function checkmethoddescriptor ****************************
600 checks whether a method-descriptor is valid and aborts otherwise.
601 All referenced classes are inserted into the list of unloaded classes.
603 *******************************************************************************/
605 static void checkmethoddescriptor (utf *d)
607 char *utf_ptr = d->text; /* current position in utf text */
608 char *end_pos = utf_end(d); /* points behind utf string */
609 char *tstart; /* pointer to start of classname */
612 /* method descriptor must start with parenthesis */
613 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
615 /* check arguments */
616 while ((c = *utf_ptr++) != ')') {
630 /* save start of classname */
633 /* determine length of classname */
634 while ( *utf_ptr++ != ';' )
635 if (utf_ptr>=end_pos)
636 panic ("Missing ';' in objecttype-descriptor");
638 /* cause loading of referenced class */
639 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
644 while ((ch = *utf_ptr++)=='[')
647 /* component type of array */
661 /* save start of classname */
664 /* determine length of classname */
665 while ( *utf_ptr++ != ';' )
666 if (utf_ptr>=end_pos)
667 panic ("Missing ';' in objecttype-descriptor");
669 /* cause loading of referenced class */
670 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
674 panic ("Ill formed methodtype-descriptor");
679 panic ("Ill formed methodtype-descriptor");
683 /* check returntype */
685 /* returntype void */
686 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
689 /* treat as field-descriptor */
690 checkfielddescriptor (utf_ptr,end_pos);
694 /******************** Function: buildarraydescriptor ***************************
696 creates a constant_arraydescriptor structure for the array type named by an
699 *******************************************************************************/
701 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
703 constant_arraydescriptor *d;
705 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
707 d = NEW (constant_arraydescriptor);
708 d -> objectclass = NULL;
709 d -> elementdescriptor = NULL;
712 count_const_pool_len += sizeof(constant_arraydescriptor);
716 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
717 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
718 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
719 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
720 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
721 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
722 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
723 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
726 d -> arraytype = ARRAYTYPE_ARRAY;
727 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
731 d -> arraytype = ARRAYTYPE_OBJECT;
733 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
734 d -> objectclass -> classUsed = NOTUSED; /* not used initially CO-RT */
735 d -> objectclass -> impldBy = NULL;
742 /******************* Function: freearraydescriptor *****************************
744 removes a structure created by buildarraydescriptor from memory
746 *******************************************************************************/
748 static void freearraydescriptor (constant_arraydescriptor *d)
751 constant_arraydescriptor *n = d->elementdescriptor;
752 FREE (d, constant_arraydescriptor);
757 /*********************** Function: displayarraydescriptor *********************/
759 static void displayarraydescriptor (constant_arraydescriptor *d)
761 switch (d->arraytype) {
762 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
763 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
764 case ARRAYTYPE_CHAR: printf ("char[]"); break;
765 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
766 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
767 case ARRAYTYPE_INT: printf ("int[]"); break;
768 case ARRAYTYPE_LONG: printf ("long[]"); break;
769 case ARRAYTYPE_SHORT: printf ("short[]"); break;
770 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
771 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
777 /******************************************************************************/
778 /************************** Functions for fields ****************************/
779 /******************************************************************************/
782 /************************ Function: field_load *********************************
784 Load everything about a class field from the class file and fill a
785 'fieldinfo' structure. For static fields, space in the data segment is
788 *******************************************************************************/
790 static void field_load (fieldinfo *f, classinfo *c)
795 f -> flags = suck_u2 (); /* ACC flags */
796 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
797 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
798 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
799 f -> offset = 0; /* offset from start of object */
803 case TYPE_INT: f->value.i = 0; break;
804 case TYPE_FLOAT: f->value.f = 0.0; break;
805 case TYPE_DOUBLE: f->value.d = 0.0; break;
806 case TYPE_ADDRESS: f->value.a = NULL;
807 heap_addreference (&(f->value.a)); /* make global reference (GC) */
811 f->value.l = 0; break;
813 f->value.l.low = 0; f->value.l.high = 0; break;
817 /* read attributes */
819 for (i=0; i<attrnum; i++) {
823 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
825 if ( aname != utf_constantvalue ) {
826 /* unknown attribute */
827 skipattributebody ();
830 /* constant value attribute */
832 /* skip attribute length */
834 /* index of value in constantpool */
837 /* initialize field with value from constantpool */
840 constant_integer *ci =
841 class_getconstant(c, pindex, CONSTANT_Integer);
842 f->value.i = ci -> value;
848 class_getconstant(c, pindex, CONSTANT_Long);
850 f->value.l = cl -> value;
856 class_getconstant(c, pindex, CONSTANT_Float);
858 f->value.f = cf->value;
863 constant_double *cd =
864 class_getconstant(c, pindex, CONSTANT_Double);
866 f->value.d = cd->value;
871 utf *u = class_getconstant(c, pindex, CONSTANT_String);
872 /* create javastring from compressed utf8-string */
873 f->value.a = literalstring_new(u);
878 log_text ("Invalid Constant - Type");
887 /********************** function: field_free **********************************/
889 static void field_free (fieldinfo *f)
895 /**************** Function: field_display (debugging only) ********************/
897 void field_display (fieldinfo *f)
900 printflags (f -> flags);
902 utf_display (f -> name);
904 utf_display (f -> descriptor);
905 printf (" offset: %ld\n", (long int) (f -> offset) );
909 /******************************************************************************/
910 /************************* Functions for methods ******************************/
911 /******************************************************************************/
914 /*********************** Function: method_load *********************************
916 Loads a method from the class file and fills an existing 'methodinfo'
917 structure. For native methods, the function pointer field is set to the
918 real function pointer, for JavaVM methods a pointer to the compiler is used
921 *******************************************************************************/
923 static void method_load (methodinfo *m, classinfo *c)
933 m -> flags = suck_u2 ();
934 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
935 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
938 m -> exceptiontable = NULL;
939 m -> entrypoint = NULL;
941 m -> stubroutine = NULL;
942 m -> methodUsed = NOTUSED;
943 m -> monoPoly = MONO;
945 m -> subRedefsUsed = 0;
949 if (! (m->flags & ACC_NATIVE) ) {
950 m -> stubroutine = createcompilerstub (m);
954 functionptr f = native_findfunction
955 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
957 m -> stubroutine = createnativestub (f, m);
963 for (i=0; i<attrnum; i++) {
966 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
968 if ( aname != utf_code) {
969 skipattributebody ();
972 if (m -> jcode) panic ("Two code-attributes for one method!");
975 m -> maxstack = suck_u2();
976 m -> maxlocals = suck_u2();
977 m -> jcodelength = suck_u4();
978 m -> jcode = MNEW (u1, m->jcodelength);
979 suck_nbytes (m->jcode, m->jcodelength);
980 m -> exceptiontablelength = suck_u2 ();
981 m -> exceptiontable =
982 MNEW (exceptiontable, m->exceptiontablelength);
985 count_vmcode_len += m->jcodelength + 18;
986 count_extable_len += 8 * m->exceptiontablelength;
989 for (e=0; e < m->exceptiontablelength; e++) {
991 m -> exceptiontable[e].startpc = suck_u2();
992 m -> exceptiontable[e].endpc = suck_u2();
993 m -> exceptiontable[e].handlerpc = suck_u2();
996 if (!idx) m -> exceptiontable[e].catchtype = NULL;
998 m -> exceptiontable[e].catchtype =
999 class_getconstant (c, idx, CONSTANT_Class);
1003 skipattributes ( suck_u2() );
1010 /********************* Function: method_free ***********************************
1012 frees all memory that was allocated for this method
1014 *******************************************************************************/
1016 static void method_free (methodinfo *m)
1018 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1019 if (m->exceptiontable)
1020 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1021 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1022 if (m->stubroutine) {
1023 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1024 else removecompilerstub (m->stubroutine);
1029 /************** Function: method_display (debugging only) **************/
1031 void method_display (methodinfo *m)
1034 printflags (m -> flags);
1036 utf_display (m -> name);
1038 utf_display (m -> descriptor);
1043 /******************** Function: method_canoverwrite ****************************
1045 Check if m and old are identical with respect to type and name. This means
1046 that old can be overwritten with m.
1048 *******************************************************************************/
1050 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1052 if (m->name != old->name) return false;
1053 if (m->descriptor != old->descriptor) return false;
1054 if (m->flags & ACC_STATIC) return false;
1061 /******************************************************************************/
1062 /************************ Functions for class *********************************/
1063 /******************************************************************************/
1066 /******************** function:: class_getconstant ******************************
1068 retrieves the value at position 'pos' of the constantpool of a class
1069 if the type of the value is other than 'ctype' the system is stopped
1071 *******************************************************************************/
1073 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1075 /* invalid position in constantpool */
1076 if (pos >= c->cpcount)
1077 panic ("Attempt to access constant outside range");
1079 /* check type of constantpool entry */
1080 if (c->cptags[pos] != ctype) {
1081 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1082 (int) ctype, (int) c->cptags[pos] );
1086 return c->cpinfos[pos];
1090 /********************* Function: class_constanttype ****************************
1092 Determines the type of a class entry in the ConstantPool
1094 *******************************************************************************/
1096 u4 class_constanttype (classinfo *c, u4 pos)
1098 if (pos >= c->cpcount)
1099 panic ("Attempt to access constant outside range");
1100 return c->cptags[pos];
1104 /******************** function: class_loadcpool ********************************
1106 loads the constantpool of a class,
1107 the entries are transformed into a simpler format
1108 by resolving references
1109 (a detailed overview of the compact structures can be found in global.h)
1111 *******************************************************************************/
1113 static void class_loadcpool (classinfo *c)
1116 /* The following structures are used to save information which cannot be
1117 processed during the first pass. After the complete constantpool has
1118 been traversed the references can be resolved.
1119 (only in specific order) */
1121 /* CONSTANT_Class_info entries */
1122 typedef struct forward_class {
1123 struct forward_class *next;
1128 /* CONSTANT_String */
1129 typedef struct forward_string {
1130 struct forward_string *next;
1135 /* CONSTANT_NameAndType */
1136 typedef struct forward_nameandtype {
1137 struct forward_nameandtype *next;
1141 } forward_nameandtype;
1143 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1144 typedef struct forward_fieldmethint {
1145 struct forward_fieldmethint *next;
1149 u2 nameandtype_index;
1150 } forward_fieldmethint;
1154 long int dumpsize = dump_size ();
1156 forward_class *forward_classes = NULL;
1157 forward_string *forward_strings = NULL;
1158 forward_nameandtype *forward_nameandtypes = NULL;
1159 forward_fieldmethint *forward_fieldmethints = NULL;
1161 /* number of entries in the constant_pool table */
1162 u4 cpcount = c -> cpcount = suck_u2();
1163 /* allocate memory */
1164 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1165 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1168 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1171 /* initialize constantpool */
1172 for (idx=0; idx<cpcount; idx++) {
1173 cptags[idx] = CONSTANT_UNUSED;
1174 cpinfos[idx] = NULL;
1178 /******* first pass *******/
1179 /* entries which cannot be resolved now are written into
1180 temporary structures and traversed again later */
1183 while (idx < cpcount) {
1184 /* get constant type */
1188 case CONSTANT_Class: {
1189 forward_class *nfc = DNEW(forward_class);
1191 nfc -> next = forward_classes;
1192 forward_classes = nfc;
1194 nfc -> thisindex = idx;
1195 /* reference to CONSTANT_NameAndType */
1196 nfc -> name_index = suck_u2 ();
1202 case CONSTANT_Fieldref:
1203 case CONSTANT_Methodref:
1204 case CONSTANT_InterfaceMethodref: {
1205 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1207 nff -> next = forward_fieldmethints;
1208 forward_fieldmethints = nff;
1210 nff -> thisindex = idx;
1213 /* class or interface type that contains the declaration of the field or method */
1214 nff -> class_index = suck_u2 ();
1215 /* name and descriptor of the field or method */
1216 nff -> nameandtype_index = suck_u2 ();
1222 case CONSTANT_String: {
1223 forward_string *nfs = DNEW (forward_string);
1225 nfs -> next = forward_strings;
1226 forward_strings = nfs;
1228 nfs -> thisindex = idx;
1229 /* reference to CONSTANT_Utf8_info with string characters */
1230 nfs -> string_index = suck_u2 ();
1236 case CONSTANT_NameAndType: {
1237 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1239 nfn -> next = forward_nameandtypes;
1240 forward_nameandtypes = nfn;
1242 nfn -> thisindex = idx;
1243 /* reference to CONSTANT_Utf8_info containing simple name */
1244 nfn -> name_index = suck_u2 ();
1245 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1246 nfn -> sig_index = suck_u2 ();
1252 case CONSTANT_Integer: {
1253 constant_integer *ci = NEW (constant_integer);
1256 count_const_pool_len += sizeof(constant_integer);
1259 ci -> value = suck_s4 ();
1260 cptags [idx] = CONSTANT_Integer;
1267 case CONSTANT_Float: {
1268 constant_float *cf = NEW (constant_float);
1271 count_const_pool_len += sizeof(constant_float);
1274 cf -> value = suck_float ();
1275 cptags [idx] = CONSTANT_Float;
1281 case CONSTANT_Long: {
1282 constant_long *cl = NEW(constant_long);
1285 count_const_pool_len += sizeof(constant_long);
1288 cl -> value = suck_s8 ();
1289 cptags [idx] = CONSTANT_Long;
1295 case CONSTANT_Double: {
1296 constant_double *cd = NEW(constant_double);
1299 count_const_pool_len += sizeof(constant_double);
1302 cd -> value = suck_double ();
1303 cptags [idx] = CONSTANT_Double;
1309 case CONSTANT_Utf8: {
1311 /* number of bytes in the bytes array (not string-length) */
1312 u4 length = suck_u2();
1313 cptags [idx] = CONSTANT_Utf8;
1314 /* insert utf-string into the utf-symboltable */
1315 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1316 /* skip bytes of the string */
1317 skip_nbytes(length);
1323 sprintf (logtext, "Unkown constant type: %d",(int) t);
1332 /* resolve entries in temporary structures */
1334 while (forward_classes) {
1336 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1338 if ( (name->blength>0) && (name->text[0]=='[') ) {
1339 /* check validity of descriptor */
1340 checkfielddescriptor (name->text, utf_end(name));
1342 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1343 cpinfos [forward_classes -> thisindex] =
1344 buildarraydescriptor(name->text, name->blength);
1348 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1349 /* retrieve class from class-table */
1350 cpinfos [forward_classes -> thisindex] = class_new (name);
1352 forward_classes = forward_classes -> next;
1356 while (forward_strings) {
1358 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1360 /* resolve utf-string */
1361 cptags [forward_strings -> thisindex] = CONSTANT_String;
1362 cpinfos [forward_strings -> thisindex] = text;
1364 forward_strings = forward_strings -> next;
1367 while (forward_nameandtypes) {
1368 constant_nameandtype *cn = NEW (constant_nameandtype);
1371 count_const_pool_len += sizeof(constant_nameandtype);
1374 /* resolve simple name and descriptor */
1375 cn -> name = class_getconstant
1376 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1377 cn -> descriptor = class_getconstant
1378 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1380 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1381 cpinfos [forward_nameandtypes -> thisindex] = cn;
1383 forward_nameandtypes = forward_nameandtypes -> next;
1387 while (forward_fieldmethints) {
1388 constant_nameandtype *nat;
1389 constant_FMIref *fmi = NEW (constant_FMIref);
1392 count_const_pool_len += sizeof(constant_FMIref);
1394 /* resolve simple name and descriptor */
1395 nat = class_getconstant
1396 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1398 fmi -> class = class_getconstant
1399 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1400 fmi -> name = nat -> name;
1401 fmi -> descriptor = nat -> descriptor;
1403 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1404 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1406 switch (forward_fieldmethints -> tag) {
1407 case CONSTANT_Fieldref: /* check validity of descriptor */
1408 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1410 case CONSTANT_InterfaceMethodref:
1411 case CONSTANT_Methodref: /* check validity of descriptor */
1412 checkmethoddescriptor (fmi->descriptor);
1416 forward_fieldmethints = forward_fieldmethints -> next;
1421 dump_release (dumpsize);
1425 /********************** Function: class_load ***********************************
1427 Loads everything interesting about a class from the class file. The
1428 'classinfo' structure must have been allocated previously.
1430 The super class and the interfaces implemented by this class need not be
1431 loaded. The link is set later by the function 'class_link'.
1433 The loaded class is removed from the list 'unloadedclasses' and added to
1434 the list 'unlinkedclasses'.
1436 *******************************************************************************/
1438 static int class_load (classinfo *c)
1444 count_class_loads++;
1447 /* output for debugging purposes */
1450 sprintf (logtext, "Loading class: ");
1451 utf_sprint (logtext+strlen(logtext), c->name );
1455 /* load classdata, throw exception on error */
1456 if (!suck_start (c->name)) {
1457 throw_classnotfoundexception();
1461 /* check signature */
1462 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1466 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1467 sprintf (logtext, "File version %d.%d is not supported",
1468 (int) ma, (int) mi);
1473 class_loadcpool (c);
1475 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1476 c -> impldBy = NULL;
1479 c -> flags = suck_u2 ();
1483 /* retrieve superclass */
1484 if ( (i = suck_u2 () ) ) {
1485 c -> super = class_getconstant (c, i, CONSTANT_Class);
1491 /* retrieve interfaces */
1492 c -> interfacescount = suck_u2 ();
1493 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1494 for (i=0; i < c -> interfacescount; i++) {
1495 c -> interfaces [i] =
1496 class_getconstant (c, suck_u2(), CONSTANT_Class);
1500 c -> fieldscount = suck_u2 ();
1501 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1502 for (i=0; i < c -> fieldscount; i++) {
1503 field_load (&(c->fields[i]), c);
1507 c -> methodscount = suck_u2 ();
1508 c -> methods = MNEW (methodinfo, c -> methodscount);
1509 for (i=0; i < c -> methodscount; i++) {
1510 method_load (&(c -> methods [i]), c);
1514 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1515 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1516 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1519 /* load variable-length attribute structures */
1520 attribute_load (suck_u2(), c);
1525 /* remove class from list of unloaded classes and
1526 add to list of unlinked classes */
1527 list_remove (&unloadedclasses, c);
1528 list_addlast (&unlinkedclasses, c);
1535 /************** internal Function: class_highestinterface ***********************
1537 Used by the function class_link to determine the amount of memory needed
1538 for the interface table.
1540 *******************************************************************************/
1542 static s4 class_highestinterface (classinfo *c)
1547 if ( ! (c->flags & ACC_INTERFACE) ) {
1548 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1549 utf_sprint (logtext+strlen(logtext), c->name);
1554 for (i=0; i<c->interfacescount; i++) {
1555 s4 h2 = class_highestinterface (c->interfaces[i]);
1562 /* class_addinterface **********************************************************
1564 Is needed by class_link for adding a VTBL to a class. All interfaces
1565 implemented by ic are added as well.
1567 *******************************************************************************/
1569 static void class_addinterface (classinfo *c, classinfo *ic)
1573 vftbl *vftbl = c->vftbl;
1575 if (i >= vftbl->interfacetablelength)
1576 panic ("Inernal error: interfacetable overflow");
1577 if (vftbl->interfacetable[-i])
1580 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1581 vftbl->interfacevftbllength[i] = 1;
1582 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1583 vftbl->interfacetable[-i][0] = NULL;
1586 vftbl->interfacevftbllength[i] = ic->methodscount;
1587 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1590 count_vftbl_len += sizeof(methodptr) *
1591 (ic->methodscount + (ic->methodscount == 0));
1594 for (j=0; j<ic->methodscount; j++) {
1597 for (m = 0; m < sc->methodscount; m++) {
1598 methodinfo *mi = &(sc->methods[m]);
1599 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1600 vftbl->interfacetable[-i][j] =
1601 vftbl->table[mi->vftblindex];
1611 for (j = 0; j < ic->interfacescount; j++)
1612 class_addinterface(c, ic->interfaces[j]);
1616 /********************** Function: class_link ***********************************
1618 Tries to link a class. The super class and every implemented interface must
1619 already have been linked. The function calculates the length in bytes that
1620 an instance of this class requires as well as the VTBL for methods and
1623 If the class can be linked, it is removed from the list 'unlinkedclasses'
1624 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1627 Attention: If cyclical class definitions are encountered, the program gets
1628 into an infinite loop (we'll have to work that out)
1630 *******************************************************************************/
1632 void class_link(classinfo *c)
1634 s4 supervftbllength; /* vftbllegnth of super class */
1635 s4 vftbllength; /* vftbllength of current class */
1636 s4 interfacetablelength; /* interface table length */
1637 classinfo *super = c->super; /* super class */
1638 classinfo *ic, *c2; /* intermediate class variables */
1639 vftbl *v; /* vftbl of current class */
1640 s4 i; /* interface/method/field counter */
1643 /* check if all superclasses are already linked, if not put c at end of
1644 unlinked list and return. Additionally initialize class fields. */
1646 /* check interfaces */
1648 for (i = 0; i < c->interfacescount; i++) {
1649 ic = c->interfaces[i];
1651 list_remove(&unlinkedclasses, c);
1652 list_addlast(&unlinkedclasses, c);
1657 /* check super class */
1659 if (super == NULL) { /* class java.long.Object */
1661 c->classUsed = USED; /* Object class is always used CO-RT*/
1662 c -> impldBy = NULL;
1663 c->instancesize = sizeof(java_objectheader);
1665 vftbllength = supervftbllength = 0;
1667 c->finalizer = NULL;
1670 if (!super->linked) {
1671 list_remove(&unlinkedclasses, c);
1672 list_addlast(&unlinkedclasses, c);
1676 if (c->flags & ACC_INTERFACE)
1677 c->index = interfaceindex++;
1679 c->index = super->index + 1;
1681 c->instancesize = super->instancesize;
1683 vftbllength = supervftbllength = super->vftbl->vftbllength;
1685 c->finalizer = super->finalizer;
1690 sprintf (logtext, "Linking Class: ");
1691 utf_sprint (logtext+strlen(logtext), c->name );
1695 /* compute vftbl length */
1697 for (i = 0; i < c->methodscount; i++) {
1698 methodinfo *m = &(c->methods[i]);
1700 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1701 classinfo *sc = super;
1704 for (j = 0; j < sc->methodscount; j++) {
1705 if (method_canoverwrite(m, &(sc->methods[j]))) {
1706 m->vftblindex = sc->methods[j].vftblindex;
1707 goto foundvftblindex;
1712 m->vftblindex = (vftbllength++);
1718 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1721 /* compute interfacetable length */
1723 interfacetablelength = 0;
1726 for (i = 0; i < c2->interfacescount; i++) {
1727 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1728 if (h > interfacetablelength)
1729 interfacetablelength = h;
1734 /* allocate virtual function table */
1736 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1737 (vftbllength - 1) + sizeof(methodptr*) *
1738 (interfacetablelength - (interfacetablelength > 0)));
1739 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1740 (interfacetablelength > 1));
1741 c->header.vftbl = c->vftbl = v;
1743 v->vftbllength = vftbllength;
1744 v->interfacetablelength = interfacetablelength;
1746 /* copy virtual function table of super class */
1748 for (i = 0; i < supervftbllength; i++)
1749 v->table[i] = super->vftbl->table[i];
1751 /* add method stubs into virtual function table */
1753 for (i = 0; i < c->methodscount; i++) {
1754 methodinfo *m = &(c->methods[i]);
1755 if (!(m->flags & ACC_STATIC)) {
1756 v->table[m->vftblindex] = m->stubroutine;
1760 /* compute instance size and offset of each field */
1762 for (i = 0; i < c->fieldscount; i++) {
1764 fieldinfo *f = &(c->fields[i]);
1766 if (!(f->flags & ACC_STATIC) ) {
1767 dsize = desc_typesize (f->descriptor);
1768 c->instancesize = ALIGN (c->instancesize, dsize);
1769 f->offset = c->instancesize;
1770 c->instancesize += dsize;
1774 /* initialize interfacetable and interfacevftbllength */
1776 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1779 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1782 for (i = 0; i < interfacetablelength; i++) {
1783 v->interfacevftbllength[i] = 0;
1784 v->interfacetable[-i] = NULL;
1787 /* add interfaces */
1789 for (c2 = c; c2 != NULL; c2 = c2->super)
1790 for (i = 0; i < c2->interfacescount; i++) {
1791 class_addinterface (c, c2->interfaces[i]);
1794 /* add finalizer method (not for java.lang.Object) */
1796 if (super != NULL) {
1798 static utf *finame = NULL;
1799 static utf *fidesc = NULL;
1802 finame = utf_finalize;
1804 fidesc = utf_fidesc;
1806 fi = class_findmethod (c, finame, fidesc);
1808 if (!(fi->flags & ACC_STATIC)) {
1818 list_remove(&unlinkedclasses, c);
1819 list_addlast(&linkedclasses, c);
1823 /******************* Function: class_freepool **********************************
1825 Frees all resources used by this classes Constant Pool.
1827 *******************************************************************************/
1829 static void class_freecpool (classinfo *c)
1835 for (idx=0; idx < c->cpcount; idx++) {
1836 tag = c->cptags[idx];
1837 info = c->cpinfos[idx];
1841 case CONSTANT_Fieldref:
1842 case CONSTANT_Methodref:
1843 case CONSTANT_InterfaceMethodref:
1844 FREE (info, constant_FMIref);
1846 case CONSTANT_Integer:
1847 FREE (info, constant_integer);
1849 case CONSTANT_Float:
1850 FREE (info, constant_float);
1853 FREE (info, constant_long);
1855 case CONSTANT_Double:
1856 FREE (info, constant_double);
1858 case CONSTANT_NameAndType:
1859 FREE (info, constant_nameandtype);
1861 case CONSTANT_Arraydescriptor:
1862 freearraydescriptor (info);
1868 MFREE (c -> cptags, u1, c -> cpcount);
1869 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1873 /*********************** Function: class_free **********************************
1875 Frees all resources used by the class.
1877 *******************************************************************************/
1879 static void class_free (classinfo *c)
1884 class_freecpool (c);
1886 MFREE (c->interfaces, classinfo*, c->interfacescount);
1888 for (i = 0; i < c->fieldscount; i++)
1889 field_free(&(c->fields[i]));
1891 for (i = 0; i < c->methodscount; i++)
1892 method_free(&(c->methods[i]));
1893 MFREE (c->methods, methodinfo, c->methodscount);
1895 if ((v = c->vftbl) != NULL) {
1896 for (i = 0; i < v->interfacetablelength; i++) {
1897 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1899 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1901 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1902 sizeof(methodptr*) * (v->interfacetablelength -
1903 (v->interfacetablelength > 0));
1904 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1905 (v->interfacetablelength > 1));
1909 if (c->innerclasscount)
1910 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1913 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1915 FREE (c, classinfo);
1918 /************************* Function: class_findfield ***************************
1920 Searches a 'classinfo' structure for a field having the given name and
1923 *******************************************************************************/
1926 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1930 for (i = 0; i < c->fieldscount; i++) {
1931 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1932 return &(c->fields[i]);
1935 panic ("Can not find field given in CONSTANT_Fieldref");
1940 /************************* Function: class_findmethod **************************
1942 Searches a 'classinfo' structure for a method having the given name and
1944 If type is NULL, it is ignored.
1946 *******************************************************************************/
1948 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1951 for (i = 0; i < c->methodscount; i++) {
1952 if ((c->methods[i].name == name) && ((desc == NULL) ||
1953 (c->methods[i].descriptor == desc)))
1954 return &(c->methods[i]);
1959 /************************* Function: class_findmethod_approx ******************
1961 like class_findmethod but ignores the return value when comparing the
1964 *******************************************************************************/
1966 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1970 for (i = 0; i < c->methodscount; i++)
1971 if (c->methods[i].name == name) {
1972 utf *meth_descr = c->methods[i].descriptor;
1976 return &(c->methods[i]);
1978 if (desc->blength <= meth_descr->blength) {
1979 /* current position in utf text */
1980 char *desc_utf_ptr = desc->text;
1981 char *meth_utf_ptr = meth_descr->text;
1982 /* points behind utf strings */
1983 char *desc_end = utf_end(desc);
1984 char *meth_end = utf_end(meth_descr);
1987 /* compare argument types */
1988 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1990 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1991 break; /* no match */
1994 return &(c->methods[i]); /* all parameter types equal */
2002 /***************** Function: class_resolvemethod_approx ***********************
2004 Searches a class and every super class for a method (without paying
2005 attention to the return value)
2007 *******************************************************************************/
2009 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2012 /* search for method (ignore returntype) */
2013 methodinfo *m = class_findmethod_approx (c, name, desc);
2016 /* search superclass */
2023 /************************* Function: class_resolvemethod ***********************
2025 Searches a class and every super class for a method.
2027 *******************************************************************************/
2029 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2032 methodinfo *m = class_findmethod(c, name, desc);
2034 /* search superclass */
2042 /************************* Function: class_issubclass **************************
2044 Checks if sub is a descendant of super.
2046 *******************************************************************************/
2048 bool class_issubclass(classinfo *sub, classinfo *super)
2051 if (!sub) return false;
2052 if (sub==super) return true;
2059 /****************** Initialization function for classes ******************
2061 In Java, every class can have a static initialization function. This
2062 function has to be called BEFORE calling other methods or accessing static
2065 *******************************************************************************/
2067 void class_init(classinfo *c)
2070 java_objectheader *exceptionptr;
2074 if (!makeinitializations)
2079 c->initialized = true;
2082 count_class_inits++;
2086 class_init(c->super);
2087 for (i = 0; i < c->interfacescount; i++)
2088 class_init(c->interfaces[i]); /* real */
2090 m = class_findmethod(c, utf_clinit, utf_fidesc);
2094 sprintf(logtext, "Class ");
2095 utf_sprint(logtext+strlen(logtext), c->name);
2096 sprintf(logtext+strlen(logtext), " has no initializer");
2102 if (!(m->flags & ACC_STATIC))
2103 panic("Class initializer is not static!");
2106 sprintf(logtext, "Starting initializer for class: ");
2107 utf_sprint(logtext + strlen(logtext), c->name);
2116 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2119 assert(blockInts == 0);
2124 printf("#### Initializer of ");
2125 utf_display(c->name);
2126 printf(" has thrown: ");
2127 utf_display(exceptionptr->vftbl->class->name);
2133 sprintf(logtext, "Finished initializer for class: ");
2134 utf_sprint(logtext + strlen(logtext), c->name);
2138 if (c->name == utf_systemclass) {
2139 /* class java.lang.System requires explicit initialization */
2142 printf("#### Initializing class System");
2144 /* find initializing method */
2145 m = class_findmethod(c,
2146 utf_initsystemclass,
2150 /* no method found */
2151 printf("initializeSystemClass failed");
2160 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2163 assert(blockInts == 0);
2168 printf("#### initializeSystemClass has thrown: ");
2169 utf_display(exceptionptr->vftbl->class->name);
2179 /********* Function: find_class_method_constant *********/
2180 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2185 for (i=0; i<c->cpcount; i++) {
2187 e = c -> cpinfos [i];
2190 switch (c -> cptags [i]) {
2191 case CONSTANT_Methodref:
2193 constant_FMIref *fmi = e;
2194 if ( (fmi->class->name == c1)
2195 && (fmi->name == m1)
2196 && (fmi->descriptor == d1)) {
2203 case CONSTANT_InterfaceMethodref:
2205 constant_FMIref *fmi = e;
2206 if ( (fmi->class->name == c1)
2207 && (fmi->name == m1)
2208 && (fmi->descriptor == d1)) {
2222 void class_showconstanti(classinfo *c, int ii)
2228 printf ("#%d: ", (int) i);
2230 switch (c->cptags [i]) {
2231 case CONSTANT_Class:
2232 printf("Classreference -> ");
2233 utf_display(((classinfo*)e)->name);
2236 case CONSTANT_Fieldref:
2237 printf("Fieldref -> "); goto displayFMIi;
2238 case CONSTANT_Methodref:
2239 printf("Methodref -> "); goto displayFMIi;
2240 case CONSTANT_InterfaceMethodref:
2241 printf("InterfaceMethod -> "); goto displayFMIi;
2244 constant_FMIref *fmi = e;
2245 utf_display(fmi->class->name);
2247 utf_display(fmi->name);
2249 utf_display(fmi->descriptor);
2253 case CONSTANT_String:
2254 printf("String -> ");
2257 case CONSTANT_Integer:
2258 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2260 case CONSTANT_Float:
2261 printf("Float -> %f", ((constant_float*)e)->value);
2263 case CONSTANT_Double:
2264 printf("Double -> %f", ((constant_double*)e)->value);
2268 u8 v = ((constant_long*)e)->value;
2270 printf("Long -> %ld", (long int) v);
2272 printf("Long -> HI: %ld, LO: %ld\n",
2273 (long int) v.high, (long int) v.low);
2277 case CONSTANT_NameAndType:
2279 constant_nameandtype *cnt = e;
2280 printf("NameAndType: ");
2281 utf_display(cnt->name);
2283 utf_display(cnt->descriptor);
2290 case CONSTANT_Arraydescriptor: {
2291 printf("Arraydescriptor: ");
2292 displayarraydescriptor(e);
2296 panic("Invalid type of ConstantPool-Entry");
2303 void class_showconstantpool (classinfo *c)
2308 printf ("---- dump of constant pool ----\n");
2310 for (i=0; i<c->cpcount; i++) {
2311 printf ("#%d: ", (int) i);
2313 e = c -> cpinfos [i];
2316 switch (c -> cptags [i]) {
2317 case CONSTANT_Class:
2318 printf ("Classreference -> ");
2319 utf_display ( ((classinfo*)e) -> name );
2322 case CONSTANT_Fieldref:
2323 printf ("Fieldref -> "); goto displayFMI;
2324 case CONSTANT_Methodref:
2325 printf ("Methodref -> "); goto displayFMI;
2326 case CONSTANT_InterfaceMethodref:
2327 printf ("InterfaceMethod -> "); goto displayFMI;
2330 constant_FMIref *fmi = e;
2331 utf_display ( fmi->class->name );
2333 utf_display ( fmi->name);
2335 utf_display ( fmi->descriptor );
2339 case CONSTANT_String:
2340 printf ("String -> ");
2343 case CONSTANT_Integer:
2344 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2346 case CONSTANT_Float:
2347 printf ("Float -> %f", ((constant_float*)e) -> value);
2349 case CONSTANT_Double:
2350 printf ("Double -> %f", ((constant_double*)e) -> value);
2354 u8 v = ((constant_long*)e) -> value;
2356 printf ("Long -> %ld", (long int) v);
2358 printf ("Long -> HI: %ld, LO: %ld\n",
2359 (long int) v.high, (long int) v.low);
2363 case CONSTANT_NameAndType:
2365 constant_nameandtype *cnt = e;
2366 printf ("NameAndType: ");
2367 utf_display (cnt->name);
2369 utf_display (cnt->descriptor);
2373 printf ("Utf8 -> ");
2376 case CONSTANT_Arraydescriptor: {
2377 printf ("Arraydescriptor: ");
2378 displayarraydescriptor (e);
2382 panic ("Invalid type of ConstantPool-Entry");
2392 /********** Function: class_showmethods (debugging only) *************/
2394 void class_showmethods (classinfo *c)
2398 printf ("--------- Fields and Methods ----------------\n");
2399 printf ("Flags: "); printflags (c->flags); printf ("\n");
2401 printf ("This: "); utf_display (c->name); printf ("\n");
2403 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2405 printf ("Index: %d\n", c->index);
2407 printf ("interfaces:\n");
2408 for (i=0; i < c-> interfacescount; i++) {
2410 utf_display (c -> interfaces[i] -> name);
2411 printf (" (%d)\n", c->interfaces[i] -> index);
2414 printf ("fields:\n");
2415 for (i=0; i < c -> fieldscount; i++) {
2416 field_display (&(c -> fields[i]));
2419 printf ("methods:\n");
2420 for (i=0; i < c -> methodscount; i++) {
2421 methodinfo *m = &(c->methods[i]);
2422 if ( !(m->flags & ACC_STATIC))
2423 printf ("vftblindex: %d ", m->vftblindex);
2425 method_display ( m );
2429 printf ("Virtual function table:\n");
2430 for (i=0; i<c->vftbl->vftbllength; i++) {
2431 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2438 /******************************************************************************/
2439 /******************* General functions for the class loader *******************/
2440 /******************************************************************************/
2442 static int loader_inited = 0;
2444 /********************* Function: loader_load ***********************************
2446 Loads and links the class desired class and each class and interface
2448 Returns: a pointer to this class
2450 *******************************************************************************/
2452 classinfo *loader_load (utf *topname)
2456 long int starttime=0,stoptime=0;
2458 intsDisable(); /* schani */
2461 starttime = getcputime();
2463 top = class_new (topname);
2466 while ( (c = list_first(&unloadedclasses)) ) {
2467 if (!class_load (c)) {
2468 list_remove (&unloadedclasses, c);
2474 while ( (c = list_first(&unlinkedclasses)) ) {
2479 loader_compute_subclasses();
2482 if (getloadingtime) {
2483 stoptime = getcputime();
2484 loadingtime += (stoptime-starttime);
2487 intsRestore(); /* schani */
2493 /**************** function: create_primitive_classes ***************************
2495 create classes representing primitive types
2497 ********************************************************************************/
2500 void create_primitive_classes()
2504 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2505 /* create primitive class */
2506 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2507 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2508 c -> impldBy = NULL;
2510 /* prevent loader from loading primitive class */
2511 list_remove (&unloadedclasses, c);
2512 /* add to unlinked classes */
2513 list_addlast (&unlinkedclasses, c);
2514 c -> super = class_java_lang_Object;
2517 primitivetype_table[i].class_primitive = c;
2519 /* create class for wrapping the primitive type */
2520 primitivetype_table[i].class_wrap =
2521 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2522 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2523 primitivetype_table[i].class_wrap -> impldBy = NULL;
2527 /***************** function: create_array_class ********************************
2529 create class representing an array
2531 ********************************************************************************/
2534 classinfo *create_array_class(utf *u)
2536 classinfo *c = class_new (u);
2537 /* prevent loader from loading the array class */
2538 list_remove (&unloadedclasses, c);
2539 /* add to unlinked classes */
2540 list_addlast (&unlinkedclasses, c);
2541 c -> super = class_java_lang_Object;
2547 /********************** Function: loader_init **********************************
2549 Initializes all lists and loads all classes required for the system or the
2552 *******************************************************************************/
2559 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
2560 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
2561 list_init(&linkedclasses, OFFSET(classinfo, listnode));
2563 /* create utf-symbols for pointer comparison of frequently used strings */
2564 utf_innerclasses = utf_new_char("InnerClasses");
2565 utf_constantvalue = utf_new_char("ConstantValue");
2566 utf_code = utf_new_char("Code");
2567 utf_finalize = utf_new_char("finalize");
2568 utf_fidesc = utf_new_char("()V");
2569 utf_clinit = utf_new_char("<clinit>");
2570 utf_initsystemclass = utf_new_char("initializeSystemClass");
2571 utf_systemclass = utf_new_char("java/lang/System");
2573 /* create class for arrays */
2574 class_array = class_new(utf_new_char("The_Array_Class"));
2575 class_array->classUsed = NOTUSED; /* not used initially CO-RT */
2576 class_array->impldBy = NULL;
2578 list_remove (&unloadedclasses, class_array);
2580 /* create class for strings, load it after class Object was loaded */
2581 string_class = utf_new_char("java/lang/String");
2582 class_java_lang_String = class_new(string_class);
2583 class_java_lang_String->classUsed = NOTUSED; /* not used initially CO-RT */
2584 class_java_lang_String->impldBy = NULL;
2586 list_remove(&unloadedclasses, class_java_lang_String);
2588 class_java_lang_Object =
2589 loader_load(utf_new_char("java/lang/Object"));
2591 list_addlast(&unloadedclasses, class_java_lang_String);
2593 class_java_lang_String =
2594 loader_load(string_class);
2595 class_java_lang_ClassCastException =
2596 loader_load(utf_new_char("java/lang/ClassCastException"));
2597 class_java_lang_NullPointerException =
2598 loader_load(utf_new_char("java/lang/NullPointerException"));
2599 class_java_lang_ArrayIndexOutOfBoundsException =
2600 loader_load(utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
2601 class_java_lang_NegativeArraySizeException =
2602 loader_load(utf_new_char("java/lang/NegativeArraySizeException"));
2603 class_java_lang_OutOfMemoryError =
2604 loader_load(utf_new_char("java/lang/OutOfMemoryError"));
2605 class_java_lang_ArrayStoreException =
2606 loader_load(utf_new_char("java/lang/ArrayStoreException"));
2607 class_java_lang_ArithmeticException =
2608 loader_load(utf_new_char("java/lang/ArithmeticException"));
2609 class_java_lang_ThreadDeath =
2610 loader_load(utf_new_char("java/lang/ThreadDeath"));
2612 /* link class for arrays */
2613 list_addlast(&unlinkedclasses, class_array);
2614 class_array->super = class_java_lang_Object;
2615 class_link(class_array);
2617 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2618 stringtable_update();
2620 /* create classes representing primitive types */
2621 create_primitive_classes();
2623 proto_java_lang_ClassCastException =
2624 builtin_new(class_java_lang_ClassCastException);
2625 heap_addreference((void**) &proto_java_lang_ClassCastException);
2627 proto_java_lang_NullPointerException =
2628 builtin_new(class_java_lang_NullPointerException);
2629 heap_addreference((void**) &proto_java_lang_NullPointerException);
2631 proto_java_lang_ArrayIndexOutOfBoundsException =
2632 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2633 heap_addreference((void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2635 proto_java_lang_NegativeArraySizeException =
2636 builtin_new(class_java_lang_NegativeArraySizeException);
2637 heap_addreference((void**) &proto_java_lang_NegativeArraySizeException);
2639 proto_java_lang_OutOfMemoryError =
2640 builtin_new(class_java_lang_OutOfMemoryError);
2641 heap_addreference((void**) &proto_java_lang_OutOfMemoryError);
2643 proto_java_lang_ArithmeticException =
2644 builtin_new(class_java_lang_ArithmeticException);
2645 heap_addreference((void**) &proto_java_lang_ArithmeticException);
2647 proto_java_lang_ArrayStoreException =
2648 builtin_new(class_java_lang_ArrayStoreException);
2649 heap_addreference((void**) &proto_java_lang_ArrayStoreException);
2651 proto_java_lang_ThreadDeath =
2652 builtin_new(class_java_lang_ThreadDeath);
2653 heap_addreference((void**) &proto_java_lang_ThreadDeath);
2661 /********************* Function: loader_initclasses ****************************
2663 Initializes all loaded but uninitialized classes
2665 *******************************************************************************/
2667 void loader_initclasses ()
2671 intsDisable(); /* schani */
2673 if (makeinitializations) {
2674 c = list_first (&linkedclasses);
2677 c = list_next (&linkedclasses, c);
2681 intsRestore(); /* schani */
2684 static s4 classvalue;
2686 static void loader_compute_class_values (classinfo *c)
2690 c->vftbl->baseval = ++classvalue;
2693 while (subs != NULL) {
2694 loader_compute_class_values(subs);
2695 subs = subs->nextsub;
2697 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2701 for (i = 0; i < c->index; i++)
2703 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2704 utf_display(c->name);
2711 void loader_compute_subclasses ()
2715 intsDisable(); /* schani */
2717 c = list_first (&linkedclasses);
2719 if (!(c->flags & ACC_INTERFACE)) {
2723 c = list_next (&linkedclasses, c);
2726 c = list_first (&linkedclasses);
2728 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2729 c->nextsub = c->super->sub;
2732 c = list_next (&linkedclasses, c);
2735 loader_compute_class_values(class_java_lang_Object);
2737 intsRestore(); /* schani */
2742 /******************** function classloader_buffer ******************************
2744 sets buffer for reading classdata
2746 *******************************************************************************/
2748 void classload_buffer(u1 *buf, int len)
2751 classbuffer_size = len;
2752 classbuf_pos = buf - 1;
2756 /******************** Function: loader_close ***********************************
2760 *******************************************************************************/
2762 void loader_close ()
2766 while ( (c=list_first(&unloadedclasses)) ) {
2767 list_remove (&unloadedclasses,c);
2770 while ( (c=list_first(&unlinkedclasses)) ) {
2771 list_remove (&unlinkedclasses,c);
2774 while ( (c=list_first(&linkedclasses)) ) {
2775 list_remove (&linkedclasses,c);
2782 * These are local overrides for various environment variables in Emacs.
2783 * Please do not remove this and leave it at the end of the file, where
2784 * Emacs will automagically detect them.
2785 * ---------------------------------------------------------------------
2788 * indent-tabs-mode: t