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
28 Changes: Andreas Krall
33 $Id: loader.c 818 2003-12-31 14:05:12Z edwin $
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
64 /* global variables ***********************************************************/
66 int count_class_infos = 0; /* variables for measurements */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
75 static s4 interfaceindex; /* sequential numbering of interfaces */
78 list unloadedclasses; /* list of all referenced but not loaded classes */
79 list unlinkedclasses; /* list of all loaded but not linked classes */
80 list linkedclasses; /* list of all completely linked classes */
83 /* utf-symbols for pointer comparison of frequently used strings */
85 static utf *utf_innerclasses; /* InnerClasses */
86 static utf *utf_constantvalue; /* ConstantValue */
87 static utf *utf_code; /* Code */
88 static utf *utf_finalize; /* finalize */
89 static utf *utf_fidesc; /* ()V changed */
90 static utf *utf_clinit; /* <clinit> */
91 static utf *utf_initsystemclass; /* initializeSystemClass */
92 static utf *utf_systemclass; /* java/lang/System */
93 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
94 static utf *utf_vmclass; /* java/lang/VMClassLoader */
95 static utf *utf_initialize;
96 static utf *utf_initializedesc;
100 static unzFile uf = 0;
112 /* important system classes ***************************************************/
114 classinfo *class_java_lang_Object;
115 classinfo *class_java_lang_String;
117 classinfo *class_java_lang_Throwable;
118 classinfo *class_java_lang_Cloneable;
119 classinfo *class_java_io_Serializable;
121 /* Pseudo classes for the typechecker */
122 classinfo *pseudo_class_Arraystub = NULL;
123 classinfo *pseudo_class_Null = NULL;
124 classinfo *pseudo_class_New = NULL;
125 vftbl *pseudo_class_Arraystub_vftbl = NULL;
128 /* These are made static so they cannot be used for throwing in native */
130 static classinfo *class_java_lang_ClassCastException;
131 static classinfo *class_java_lang_NullPointerException;
132 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
133 static classinfo *class_java_lang_NegativeArraySizeException;
134 static classinfo *class_java_lang_OutOfMemoryError;
135 static classinfo *class_java_lang_ArithmeticException;
136 static classinfo *class_java_lang_ArrayStoreException;
137 static classinfo *class_java_lang_ThreadDeath;
139 static methodinfo method_clone_array;
141 static int loader_inited = 0;
144 /******************************************************************************
146 structure for primitive classes: contains the class for wrapping the
147 primitive type, the primitive class, the name of the class for wrapping,
148 the one character type signature and the name of the primitive class
150 ******************************************************************************/
152 /* CAUTION: Don't change the order of the types. This table is indexed
153 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
155 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
156 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
157 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
158 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
159 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
160 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
161 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
162 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
163 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
164 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
168 /* instances of important system classes **************************************/
170 java_objectheader *proto_java_lang_ClassCastException;
171 java_objectheader *proto_java_lang_NullPointerException;
172 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
173 java_objectheader *proto_java_lang_NegativeArraySizeException;
174 java_objectheader *proto_java_lang_OutOfMemoryError;
175 java_objectheader *proto_java_lang_ArithmeticException;
176 java_objectheader *proto_java_lang_ArrayStoreException;
177 java_objectheader *proto_java_lang_ThreadDeath;
179 /************* functions for reading classdata *********************************
181 getting classdata in blocks of variable size
182 (8,16,32,64-bit integer or float)
184 *******************************************************************************/
186 static char *classpath = ""; /* searchpath for classfiles */
187 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
188 static u1 *classbuf_pos; /* current position in classfile buffer */
189 static int classbuffer_size; /* size of classfile-data */
191 /* assert that at least <len> bytes are left to read */
192 /* <len> is limited to the range of non-negative s4 values */
193 #define ASSERT_LEFT(len) \
194 do {if ( ((s4)(len)) < 0 \
195 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
196 panic("Unexpected end of classfile"); } while(0)
198 /* transfer block of classfile data into a buffer */
200 #define suck_nbytes(buffer,len) \
201 do {ASSERT_LEFT(len); \
202 memcpy(buffer,classbuf_pos+1,len); \
203 classbuf_pos+=len;} while (0)
205 /* skip block of classfile data */
207 #define skip_nbytes(len) \
208 do {ASSERT_LEFT(len); \
209 classbuf_pos+=len;} while(0)
214 return *++classbuf_pos;
218 u1 a=suck_u1(), b=suck_u1();
219 return ((u2)a<<8)+(u2)b;
223 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
224 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
226 #define suck_s8() (s8) suck_u8()
227 #define suck_s2() (s2) suck_u2()
228 #define suck_s4() (s4) suck_u4()
229 #define suck_s1() (s1) suck_u1()
232 /* get u8 from classfile data */
239 return (hi << 32) + lo;
249 /* get float from classfile data */
250 static float suck_float()
257 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
258 memcpy((u1*) (&f), buffer, 4);
260 suck_nbytes((u1*) (&f), 4);
263 PANICIF (sizeof(float) != 4, "Incompatible float-format");
269 /* get double from classfile data */
270 static double suck_double()
277 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
278 memcpy((u1*) (&d), buffer, 8);
280 suck_nbytes((u1*) (&d), 8);
283 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
289 /************************** function suck_init *********************************
291 called once at startup, sets the searchpath for the classfiles
293 *******************************************************************************/
295 void suck_init(char *cpath)
302 /************************** function suck_start ********************************
304 returns true if classbuffer is already loaded or a file for the
305 specified class has succussfully been read in. All directories of
306 the searchpath are used to find the classfile (<classname>.class).
307 Returns false if no classfile is found and writes an error message.
309 *******************************************************************************/
311 bool suck_start(utf *classname)
314 #define MAXFILENAME 1000 /* maximum length of a filename */
316 char filename[MAXFILENAME+10]; /* room for '.class' */
317 char *pathpos; /* position in searchpath */
318 char c, *utf_ptr; /* pointer to the next utf8-character */
320 int filenamelen, err;
324 if (classbuffer) /* classbuffer is already valid */
331 /* skip path separator */
333 while (*pathpos == ':')
336 /* extract directory from searchpath */
339 while ((*pathpos) && (*pathpos != ':')) {
340 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
341 filename[filenamelen++] = *(pathpos++);
345 if (filenamelen > 4) {
346 if ( ((filename[filenamelen - 1] == 'p') || (filename[filenamelen - 1] == 'P')) &
347 ((filename[filenamelen - 2] == 'i') || (filename[filenamelen - 2] == 'I')) &
348 ((filename[filenamelen - 3] == 'z') || (filename[filenamelen - 3] == 'Z')) ) {
355 filename[filenamelen++] = '\0';
356 if (uf == 0) uf = unzOpen(filename);
358 utf_ptr = classname->text;
360 while (utf_ptr < utf_end(classname)) {
361 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
363 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
365 filename[filenamelen++] = c;
367 strcpy(filename + filenamelen, ".class");
368 if (cacao_locate(uf,classname) == UNZ_OK) {
369 unz_file_info file_info;
370 log_text("Class found in zip file");
371 if (unzGetCurrentFileInfo(uf, &file_info, filename,
372 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
373 if (unzOpenCurrentFile(uf) == UNZ_OK) {
374 classbuffer_size = file_info.uncompressed_size;
375 classbuffer = MNEW(u1, classbuffer_size);
376 classbuf_pos = classbuffer - 1;
377 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
378 if (unzReadCurrentFile(uf, classbuffer, classbuffer_size) == classbuffer_size) {
379 unzCloseCurrentFile(uf);
382 MFREE(classbuffer, u1, classbuffer_size);
383 log_text("Error while unzipping");
385 } else log_text("Error while opening file in archive");
386 } else log_text("Error while retrieving fileinfo");
388 unzCloseCurrentFile(uf);
393 filename[filenamelen++] = '/';
395 /* add classname to filename */
397 utf_ptr = classname->text;
398 while (utf_ptr < utf_end(classname)) {
399 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
401 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
403 filename[filenamelen++] = c;
408 strcpy(filename + filenamelen, ".class");
410 classfile = fopen(filename, "r");
411 if (classfile) { /* file exists */
413 /* determine size of classfile */
415 /* dolog("File: %s",filename); */
417 err = stat(filename, &buffer);
419 if (!err) { /* read classfile data */
420 classbuffer_size = buffer.st_size;
421 classbuffer = MNEW(u1, classbuffer_size);
422 classbuf_pos = classbuffer - 1;
423 fread(classbuffer, 1, classbuffer_size, classfile);
431 dolog("Warning: Can not open class file '%s'", filename);
438 /************************** function suck_stop *********************************
440 frees memory for buffer with classfile data.
441 Caution: this function may only be called if buffer has been allocated
442 by suck_start with reading a file
444 *******************************************************************************/
448 /* determine amount of classdata not retrieved by suck-operations */
450 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
452 if (classdata_left > 0) {
454 dolog("There are %d access bytes at end of classfile",
461 MFREE(classbuffer, u1, classbuffer_size);
466 /******************************************************************************/
467 /******************* Some support functions ***********************************/
468 /******************************************************************************/
470 void fprintflags (FILE *fp, u2 f)
472 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
473 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
474 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
475 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
476 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
477 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
478 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
479 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
480 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
481 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
482 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
486 /********** internal function: printflags (only for debugging) ***************/
488 void printflags(u2 f)
490 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
491 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
492 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
493 if ( f & ACC_STATIC ) printf (" STATIC");
494 if ( f & ACC_FINAL ) printf (" FINAL");
495 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
496 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
497 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
498 if ( f & ACC_NATIVE ) printf (" NATIVE");
499 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
500 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
504 /************************* Function: skipattribute *****************************
506 skips a (1) 'attribute' structure in the class file
508 *******************************************************************************/
510 static void skipattribute()
519 /********************** Function: skipattributebody ****************************
521 skips an attribute after the 16 bit reference to attribute_name has already
524 *******************************************************************************/
526 static void skipattributebody()
534 /************************* Function: skipattributes ****************************
536 skips num attribute structures
538 *******************************************************************************/
540 static void skipattributes(u4 num)
543 for (i = 0; i < num; i++)
548 /******************** function: innerclass_getconstant ************************
550 like class_getconstant, but if cptags is ZERO null is returned
552 *******************************************************************************/
554 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
556 /* invalid position in constantpool */
557 if (pos >= c->cpcount)
558 panic("Attempt to access constant outside range");
560 /* constantpool entry of type 0 */
564 /* check type of constantpool entry */
565 if (c->cptags[pos] != ctype) {
566 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
567 (int) ctype, (int) c->cptags[pos] );
570 return c->cpinfos[pos];
574 /************************ function: attribute_load ****************************
576 read attributes from classfile
578 *******************************************************************************/
580 static void attribute_load(u4 num, classinfo *c)
584 for (i = 0; i < num; i++) {
585 /* retrieve attribute name */
586 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
588 if (aname == utf_innerclasses) {
589 /* innerclasses attribute */
591 /* skip attribute length */
593 /* number of records */
594 c->innerclasscount = suck_u2();
595 /* allocate memory for innerclass structure */
596 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
598 for (j = 0; j < c->innerclasscount; j++) {
599 /* The innerclass structure contains a class with an encoded name,
600 its defining scope, its simple name and a bitmask of the access flags.
601 If an inner class is not a member, its outer_class is NULL,
602 if a class is anonymous, its name is NULL. */
604 innerclassinfo *info = c->innerclass + j;
606 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
607 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
608 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
609 info->flags = suck_u2(); /* access_flags bitmask */
613 /* unknown attribute */
620 /******************* function: checkfielddescriptor ****************************
622 checks whether a field-descriptor is valid and aborts otherwise
623 all referenced classes are inserted into the list of unloaded classes
625 *******************************************************************************/
627 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
629 class_from_descriptor(utf_ptr,end_pos,NULL,
631 | CLASSLOAD_NULLPRIMITIVE
633 | CLASSLOAD_CHECKEND);
635 char *tstart; /* pointer to start of classname */
637 char *start = utf_ptr;
639 switch (*utf_ptr++) {
653 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
654 panic ("Ill formed descriptor");
658 panic ("Ill formed descriptor");
661 /* exceeding characters */
662 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
667 /******************* function checkmethoddescriptor ****************************
669 checks whether a method-descriptor is valid and aborts otherwise.
670 All referenced classes are inserted into the list of unloaded classes.
672 *******************************************************************************/
674 static void checkmethoddescriptor (utf *d)
676 char *utf_ptr = d->text; /* current position in utf text */
677 char *end_pos = utf_end(d); /* points behind utf string */
679 /* method descriptor must start with parenthesis */
680 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
682 /* check arguments */
683 while (utf_ptr != end_pos && *utf_ptr != ')') {
684 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
686 | CLASSLOAD_NULLPRIMITIVE
690 if (utf_ptr == end_pos) panic("Missing return type in method descriptor");
691 utf_ptr++; /* skip ')' */
693 class_from_descriptor(utf_ptr,end_pos,NULL,
695 | CLASSLOAD_NULLPRIMITIVE
696 | CLASSLOAD_CHECKEND);
699 /* XXX check length */
700 /* check arguments */
701 while ((c = *utf_ptr++) != ')') {
718 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
719 panic ("Ill formed method descriptor");
723 panic ("Ill formed methodtype-descriptor");
727 /* check returntype */
729 /* returntype void */
730 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
733 /* treat as field-descriptor */
734 checkfielddescriptor (utf_ptr,end_pos);
739 /***************** Function: print_arraydescriptor ****************************
741 Debugging helper for displaying an arraydescriptor
743 *******************************************************************************/
745 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
748 fprintf(file, "<NULL>");
753 if (desc->componentvftbl) {
754 if (desc->componentvftbl->class)
755 utf_fprint(file, desc->componentvftbl->class->name);
757 fprintf(file, "<no classinfo>");
763 if (desc->elementvftbl) {
764 if (desc->elementvftbl->class)
765 utf_fprint(file, desc->elementvftbl->class->name);
767 fprintf(file, "<no classinfo>");
771 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
772 desc->dataoffset, desc->componentsize);
776 /******************************************************************************/
777 /************************** Functions for fields ****************************/
778 /******************************************************************************/
781 /************************ Function: field_load *********************************
783 Load everything about a class field from the class file and fill a
784 'fieldinfo' structure. For static fields, space in the data segment is
787 *******************************************************************************/
789 static void field_load(fieldinfo *f, classinfo *c)
794 f->flags = suck_u2(); /* ACC flags */
795 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
796 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
797 f->type = jtype = desc_to_type(f->descriptor); /* data type */
798 f->offset = 0; /* offset from start of object */
802 /* check flag consistency */
804 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
805 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
806 panic("Field has invalid access flags");
807 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
808 panic("Field is declared final and volatile");
809 if ((c->flags & ACC_INTERFACE) != 0) {
810 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
811 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
812 panic("Interface field is not declared static final public");
817 case TYPE_INT: f->value.i = 0; break;
818 case TYPE_FLOAT: f->value.f = 0.0; break;
819 case TYPE_DOUBLE: f->value.d = 0.0; break;
820 case TYPE_ADDRESS: f->value.a = NULL; break;
823 f->value.l = 0; break;
825 f->value.l.low = 0; f->value.l.high = 0; break;
829 /* read attributes */
831 for (i = 0; i < attrnum; i++) {
835 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
837 if (aname != utf_constantvalue) {
838 /* unknown attribute */
842 /* constant value attribute */
844 /* skip attribute length */
846 /* index of value in constantpool */
849 /* initialize field with value from constantpool */
852 constant_integer *ci =
853 class_getconstant(c, pindex, CONSTANT_Integer);
854 f->value.i = ci->value;
860 class_getconstant(c, pindex, CONSTANT_Long);
861 f->value.l = cl->value;
867 class_getconstant(c, pindex, CONSTANT_Float);
868 f->value.f = cf->value;
873 constant_double *cd =
874 class_getconstant(c, pindex, CONSTANT_Double);
875 f->value.d = cd->value;
880 utf *u = class_getconstant(c, pindex, CONSTANT_String);
881 /* create javastring from compressed utf8-string */
882 f->value.a = literalstring_new(u);
887 log_text ("Invalid Constant - Type");
894 /********************** function: field_free **********************************/
896 static void field_free (fieldinfo *f)
902 /**************** Function: field_display (debugging only) ********************/
904 void field_display(fieldinfo *f)
907 printflags(f->flags);
909 utf_display(f->name);
911 utf_display(f->descriptor);
912 printf(" offset: %ld\n", (long int) (f->offset));
916 /******************************************************************************/
917 /************************* Functions for methods ******************************/
918 /******************************************************************************/
921 /*********************** Function: method_load *********************************
923 Loads a method from the class file and fills an existing 'methodinfo'
924 structure. For native methods, the function pointer field is set to the
925 real function pointer, for JavaVM methods a pointer to the compiler is used
928 *******************************************************************************/
930 static void method_load(methodinfo *m, classinfo *c)
933 static utf* name_init = NULL;
934 static utf* name_clinit = NULL;
942 m->flags = suck_u2();
943 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
944 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
945 checkmethoddescriptor(m->descriptor);
947 /* check flag consistency */
950 name_init = utf_new_char("<init>");
951 name_clinit = utf_new_char("<clinit>");
953 /* XXX could check if <clinit> is STATIC */
954 if (m->name != name_clinit) {
955 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
956 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
957 panic("Method has invalid access flags");
958 if ((m->flags & ACC_ABSTRACT) != 0) {
959 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
960 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
961 panic("Abstract method has invalid flags set");
963 if ((c->flags & ACC_INTERFACE) != 0) {
964 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
965 != (ACC_ABSTRACT | ACC_PUBLIC))
966 panic("Interface method is not declared abstract and public");
968 if (m->name == name_init) {
969 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
970 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
971 panic("Instance initialization method has invalid flags set");
977 m->exceptiontable = NULL;
978 m->entrypoint = NULL;
980 m->stubroutine = NULL;
981 m->methodUsed = NOTUSED;
984 m->subRedefsUsed = 0;
988 if (!(m->flags & ACC_NATIVE)) {
989 m->stubroutine = createcompilerstub(m);
992 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
993 (m->flags & ACC_STATIC) != 0);
995 m->stubroutine = createnativestub(f, m);
1000 attrnum = suck_u2();
1001 for (i = 0; i < attrnum; i++) {
1004 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1006 if (aname != utf_code) {
1007 skipattributebody();
1012 panic("Two code-attributes for one method!");
1015 m->maxstack = suck_u2();
1016 m->maxlocals = suck_u2();
1017 codelen = suck_u4();
1019 panic("bytecode has zero length");
1020 if (codelen > 65536)
1021 panic("bytecode too long");
1022 m->jcodelength = codelen;
1023 m->jcode = MNEW(u1, m->jcodelength);
1024 suck_nbytes(m->jcode, m->jcodelength);
1025 m->exceptiontablelength = suck_u2();
1027 MNEW(exceptiontable, m->exceptiontablelength);
1030 count_vmcode_len += m->jcodelength + 18;
1031 count_extable_len += 8 * m->exceptiontablelength;
1034 for (e = 0; e < m->exceptiontablelength; e++) {
1036 m->exceptiontable[e].startpc = suck_u2();
1037 m->exceptiontable[e].endpc = suck_u2();
1038 m->exceptiontable[e].handlerpc = suck_u2();
1042 m->exceptiontable[e].catchtype = NULL;
1045 m->exceptiontable[e].catchtype =
1046 class_getconstant(c, idx, CONSTANT_Class);
1050 skipattributes(suck_u2());
1056 /********************* Function: method_free ***********************************
1058 frees all memory that was allocated for this method
1060 *******************************************************************************/
1062 static void method_free(methodinfo *m)
1065 MFREE(m->jcode, u1, m->jcodelength);
1067 if (m->exceptiontable)
1068 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1071 CFREE(m->mcode, m->mcodelength);
1073 if (m->stubroutine) {
1074 if (m->flags & ACC_NATIVE) {
1075 removenativestub(m->stubroutine);
1078 removecompilerstub(m->stubroutine);
1084 /************** Function: method_display (debugging only) **************/
1086 void method_display(methodinfo *m)
1089 printflags(m->flags);
1091 utf_display(m->name);
1093 utf_display(m->descriptor);
1098 /******************** Function: method_canoverwrite ****************************
1100 Check if m and old are identical with respect to type and name. This means
1101 that old can be overwritten with m.
1103 *******************************************************************************/
1105 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1107 if (m->name != old->name) return false;
1108 if (m->descriptor != old->descriptor) return false;
1109 if (m->flags & ACC_STATIC) return false;
1116 /******************************************************************************/
1117 /************************ Functions for class *********************************/
1118 /******************************************************************************/
1121 /******************** function:: class_getconstant ******************************
1123 retrieves the value at position 'pos' of the constantpool of a class
1124 if the type of the value is other than 'ctype' the system is stopped
1126 *******************************************************************************/
1128 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1130 /* invalid position in constantpool */
1131 /* (pos == 0 is caught by type comparison) */
1132 if (pos >= c->cpcount)
1133 panic("Attempt to access constant outside range");
1135 /* check type of constantpool entry */
1137 if (c->cptags[pos] != ctype) {
1138 class_showconstantpool(c);
1139 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1140 (int) ctype, (int) c->cptags[pos]);
1143 return c->cpinfos[pos];
1147 /********************* Function: class_constanttype ****************************
1149 Determines the type of a class entry in the ConstantPool
1151 *******************************************************************************/
1153 u4 class_constanttype(classinfo *c, u4 pos)
1155 if (pos >= c->cpcount)
1156 panic("Attempt to access constant outside range");
1158 return c->cptags[pos];
1162 /******************** function: class_loadcpool ********************************
1164 loads the constantpool of a class,
1165 the entries are transformed into a simpler format
1166 by resolving references
1167 (a detailed overview of the compact structures can be found in global.h)
1169 *******************************************************************************/
1171 static void class_loadcpool(classinfo *c)
1174 /* The following structures are used to save information which cannot be
1175 processed during the first pass. After the complete constantpool has
1176 been traversed the references can be resolved.
1177 (only in specific order) */
1179 /* CONSTANT_Class_info entries */
1180 typedef struct forward_class {
1181 struct forward_class *next;
1186 /* CONSTANT_String */
1187 typedef struct forward_string {
1188 struct forward_string *next;
1193 /* CONSTANT_NameAndType */
1194 typedef struct forward_nameandtype {
1195 struct forward_nameandtype *next;
1199 } forward_nameandtype;
1201 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1202 typedef struct forward_fieldmethint {
1203 struct forward_fieldmethint *next;
1207 u2 nameandtype_index;
1208 } forward_fieldmethint;
1212 long int dumpsize = dump_size ();
1214 forward_class *forward_classes = NULL;
1215 forward_string *forward_strings = NULL;
1216 forward_nameandtype *forward_nameandtypes = NULL;
1217 forward_fieldmethint *forward_fieldmethints = NULL;
1219 /* number of entries in the constant_pool table plus one */
1220 u4 cpcount = c -> cpcount = suck_u2();
1221 /* allocate memory */
1222 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1223 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1226 panic("Invalid constant_pool_count (0)");
1229 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1232 /* initialize constantpool */
1233 for (idx=0; idx<cpcount; idx++) {
1234 cptags[idx] = CONSTANT_UNUSED;
1235 cpinfos[idx] = NULL;
1239 /******* first pass *******/
1240 /* entries which cannot be resolved now are written into
1241 temporary structures and traversed again later */
1244 while (idx < cpcount) {
1245 /* get constant type */
1249 case CONSTANT_Class: {
1250 forward_class *nfc = DNEW(forward_class);
1252 nfc -> next = forward_classes;
1253 forward_classes = nfc;
1255 nfc -> thisindex = idx;
1256 /* reference to CONSTANT_NameAndType */
1257 nfc -> name_index = suck_u2 ();
1263 case CONSTANT_Fieldref:
1264 case CONSTANT_Methodref:
1265 case CONSTANT_InterfaceMethodref: {
1266 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1268 nff -> next = forward_fieldmethints;
1269 forward_fieldmethints = nff;
1271 nff -> thisindex = idx;
1274 /* class or interface type that contains the declaration of the field or method */
1275 nff -> class_index = suck_u2 ();
1276 /* name and descriptor of the field or method */
1277 nff -> nameandtype_index = suck_u2 ();
1283 case CONSTANT_String: {
1284 forward_string *nfs = DNEW (forward_string);
1286 nfs -> next = forward_strings;
1287 forward_strings = nfs;
1289 nfs -> thisindex = idx;
1290 /* reference to CONSTANT_Utf8_info with string characters */
1291 nfs -> string_index = suck_u2 ();
1297 case CONSTANT_NameAndType: {
1298 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1300 nfn -> next = forward_nameandtypes;
1301 forward_nameandtypes = nfn;
1303 nfn -> thisindex = idx;
1304 /* reference to CONSTANT_Utf8_info containing simple name */
1305 nfn -> name_index = suck_u2 ();
1306 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1307 nfn -> sig_index = suck_u2 ();
1313 case CONSTANT_Integer: {
1314 constant_integer *ci = NEW (constant_integer);
1317 count_const_pool_len += sizeof(constant_integer);
1320 ci -> value = suck_s4 ();
1321 cptags [idx] = CONSTANT_Integer;
1328 case CONSTANT_Float: {
1329 constant_float *cf = NEW (constant_float);
1332 count_const_pool_len += sizeof(constant_float);
1335 cf -> value = suck_float ();
1336 cptags [idx] = CONSTANT_Float;
1342 case CONSTANT_Long: {
1343 constant_long *cl = NEW(constant_long);
1346 count_const_pool_len += sizeof(constant_long);
1349 cl -> value = suck_s8 ();
1350 cptags [idx] = CONSTANT_Long;
1354 panic("Long constant exceeds constant pool");
1358 case CONSTANT_Double: {
1359 constant_double *cd = NEW(constant_double);
1362 count_const_pool_len += sizeof(constant_double);
1365 cd -> value = suck_double ();
1366 cptags [idx] = CONSTANT_Double;
1370 panic("Double constant exceeds constant pool");
1374 case CONSTANT_Utf8: {
1376 /* number of bytes in the bytes array (not string-length) */
1377 u4 length = suck_u2();
1378 cptags [idx] = CONSTANT_Utf8;
1379 /* validate the string */
1380 ASSERT_LEFT(length);
1382 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1383 panic("Invalid UTF-8 string");
1384 /* insert utf-string into the utf-symboltable */
1385 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1386 /* skip bytes of the string */
1387 skip_nbytes(length);
1393 error ("Unkown constant type: %d",(int) t);
1401 /* resolve entries in temporary structures */
1403 while (forward_classes) {
1405 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1407 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1408 /* retrieve class from class-table */
1409 cpinfos [forward_classes -> thisindex] = class_new (name);
1411 forward_classes = forward_classes -> next;
1415 while (forward_strings) {
1417 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1419 log_text("forward_string:");
1420 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1422 log_text("\n------------------"); */
1423 /* resolve utf-string */
1424 cptags [forward_strings -> thisindex] = CONSTANT_String;
1425 cpinfos [forward_strings -> thisindex] = text;
1427 forward_strings = forward_strings -> next;
1430 while (forward_nameandtypes) {
1431 constant_nameandtype *cn = NEW (constant_nameandtype);
1434 count_const_pool_len += sizeof(constant_nameandtype);
1437 /* resolve simple name and descriptor */
1438 cn -> name = class_getconstant
1439 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1440 cn -> descriptor = class_getconstant
1441 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1443 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1444 cpinfos [forward_nameandtypes -> thisindex] = cn;
1446 forward_nameandtypes = forward_nameandtypes -> next;
1450 while (forward_fieldmethints) {
1451 constant_nameandtype *nat;
1452 constant_FMIref *fmi = NEW (constant_FMIref);
1455 count_const_pool_len += sizeof(constant_FMIref);
1457 /* resolve simple name and descriptor */
1458 nat = class_getconstant
1459 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1462 log_text("trying to resolve:");
1463 log_text(nat->name->text);
1464 switch(forward_fieldmethints ->tag) {
1465 case CONSTANT_Fieldref:
1466 log_text("CONSTANT_Fieldref");
1468 case CONSTANT_InterfaceMethodref:
1469 log_text("CONSTANT_InterfaceMethodref");
1471 case CONSTANT_Methodref:
1472 log_text("CONSTANT_Methodref");
1476 fmi -> class = class_getconstant
1477 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1478 fmi -> name = nat -> name;
1479 fmi -> descriptor = nat -> descriptor;
1481 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1482 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1484 switch (forward_fieldmethints -> tag) {
1485 case CONSTANT_Fieldref: /* check validity of descriptor */
1486 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1488 case CONSTANT_InterfaceMethodref:
1489 case CONSTANT_Methodref: /* check validity of descriptor */
1490 /* XXX check special names (<init>) */
1491 checkmethoddescriptor (fmi->descriptor);
1495 forward_fieldmethints = forward_fieldmethints -> next;
1499 /* class_showconstantpool(c); */
1501 dump_release (dumpsize);
1505 /********************** Function: class_load ***********************************
1507 Loads everything interesting about a class from the class file. The
1508 'classinfo' structure must have been allocated previously.
1510 The super class and the interfaces implemented by this class need not be
1511 loaded. The link is set later by the function 'class_link'.
1513 The loaded class is removed from the list 'unloadedclasses' and added to
1514 the list 'unlinkedclasses'.
1516 *******************************************************************************/
1518 static int class_load(classinfo *c)
1524 count_class_loads++;
1527 /* output for debugging purposes */
1529 char logtext[MAXLOGTEXT];
1530 sprintf(logtext, "Loading class: ");
1531 utf_sprint(logtext + strlen(logtext), c->name);
1535 /* load classdata, throw exception on error */
1537 if (!suck_start(c->name)) {
1538 throw_noclassdeffounderror_message(c->name);
1542 /* check signature */
1543 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1547 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1548 error("File version %d.%d is not supported", (int) ma, (int) mi);
1553 c->erroneous_state = 0;
1554 c->initializing_thread = 0;
1556 c->classUsed = NOTUSED; /* not used initially CO-RT */
1560 c->flags = suck_u2();
1561 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1563 /* check ACC flags consistency */
1564 if ((c->flags & ACC_INTERFACE) != 0) {
1565 if ((c->flags & ACC_ABSTRACT) == 0)
1566 panic("Interface class not declared abstract");
1567 if ((c->flags & (ACC_FINAL | ACC_SUPER)) != 0)
1568 panic("Interface class has invalid flags");
1572 suck_u2(); /* XXX check it? */
1574 /* retrieve superclass */
1575 if ((i = suck_u2())) {
1576 c->super = class_getconstant(c, i, CONSTANT_Class);
1582 /* retrieve interfaces */
1583 c->interfacescount = suck_u2();
1584 c->interfaces = MNEW(classinfo*, c->interfacescount);
1585 for (i = 0; i < c->interfacescount; i++) {
1587 class_getconstant(c, suck_u2(), CONSTANT_Class);
1591 c->fieldscount = suck_u2();
1592 /* utf_display(c->name);
1593 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1595 c->fields = GCNEW(fieldinfo, c->fieldscount);
1596 for (i = 0; i < c->fieldscount; i++) {
1597 field_load(&(c->fields[i]), c);
1601 c->methodscount = suck_u2();
1602 c->methods = MNEW(methodinfo, c->methodscount);
1603 for (i = 0; i < c->methodscount; i++) {
1604 method_load(&(c->methods[i]), c);
1608 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1609 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1610 count_class_infos += sizeof(methodinfo) * c->methodscount;
1613 /* load variable-length attribute structures */
1614 attribute_load(suck_u2(), c);
1619 /* remove class from list of unloaded classes and
1620 add to list of unlinked classes */
1621 list_remove(&unloadedclasses, c);
1622 list_addlast(&unlinkedclasses, c);
1631 /************** internal Function: class_highestinterface ***********************
1633 Used by the function class_link to determine the amount of memory needed
1634 for the interface table.
1636 *******************************************************************************/
1638 static s4 class_highestinterface(classinfo *c)
1643 if (!(c->flags & ACC_INTERFACE)) {
1644 char logtext[MAXLOGTEXT];
1645 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1646 utf_sprint(logtext + strlen(logtext), c->name);
1647 error("%s",logtext);
1651 for (i = 0; i < c->interfacescount; i++) {
1652 s4 h2 = class_highestinterface(c->interfaces[i]);
1660 /* class_addinterface **********************************************************
1662 Is needed by class_link for adding a VTBL to a class. All interfaces
1663 implemented by ic are added as well.
1665 *******************************************************************************/
1667 static void class_addinterface (classinfo *c, classinfo *ic)
1671 vftbl *vftbl = c->vftbl;
1673 if (i >= vftbl->interfacetablelength)
1674 panic ("Inernal error: interfacetable overflow");
1675 if (vftbl->interfacetable[-i])
1678 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1679 vftbl->interfacevftbllength[i] = 1;
1680 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1681 vftbl->interfacetable[-i][0] = NULL;
1684 vftbl->interfacevftbllength[i] = ic->methodscount;
1685 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1688 count_vftbl_len += sizeof(methodptr) *
1689 (ic->methodscount + (ic->methodscount == 0));
1692 for (j=0; j<ic->methodscount; j++) {
1695 for (m = 0; m < sc->methodscount; m++) {
1696 methodinfo *mi = &(sc->methods[m]);
1697 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1698 vftbl->interfacetable[-i][j] =
1699 vftbl->table[mi->vftblindex];
1709 for (j = 0; j < ic->interfacescount; j++)
1710 class_addinterface(c, ic->interfaces[j]);
1714 /******************* Function: class_new_array *********************************
1716 This function is called by class_new to setup an array class.
1718 *******************************************************************************/
1720 void class_new_array(classinfo *c)
1722 classinfo *comp = NULL;
1726 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1728 /* Array classes are not loaded from classfiles. */
1729 list_remove(&unloadedclasses, c);
1731 /* Check array class name */
1732 namelen = c->name->blength;
1733 if (namelen < 2 || c->name->text[0] != '[')
1734 panic("Invalid array class name");
1736 /* Check the component type */
1737 switch (c->name->text[1]) {
1739 /* c is an array of arrays. We have to create the component class. */
1740 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1744 /* c is an array of objects. */
1745 if (namelen < 4 || c->name->text[namelen - 1] != ';')
1746 panic("Invalid array class name");
1747 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1751 /* Setup the array class */
1752 c->super = class_java_lang_Object;
1753 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1755 c->interfacescount = 2;
1756 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1757 c->interfaces[0] = class_java_lang_Cloneable;
1758 c->interfaces[1] = class_java_io_Serializable;
1760 c->methodscount = 1;
1761 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1764 memset(clone, 0, sizeof(methodinfo));
1765 clone->flags = ACC_PUBLIC; /* XXX protected? */
1766 clone->name = utf_new_char("clone");
1767 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1769 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
1770 clone->monoPoly = MONO; /* XXX should be poly? */
1772 /* XXX: field: length? */
1774 /* The array class has to be linked */
1775 list_addlast(&unlinkedclasses,c);
1778 * Array classes which are created after the other classes have been
1779 * loaded and linked are linked explicitely.
1784 loader_load(c->name); /* XXX handle errors */
1788 /****************** Function: class_link_array *********************************
1790 This function is called by class_link to create the
1791 arraydescriptor for an array class.
1793 This function returns NULL if the array cannot be linked because
1794 the component type has not been linked yet.
1796 *******************************************************************************/
1798 static arraydescriptor *class_link_array(classinfo *c)
1800 classinfo *comp = NULL;
1801 int namelen = c->name->blength;
1802 arraydescriptor *desc;
1805 /* Check the component type */
1806 switch (c->name->text[1]) {
1808 /* c is an array of arrays. */
1809 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1810 if (!comp) panic("Could not find component array class.");
1814 /* c is an array of objects. */
1815 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1816 if (!comp) panic("Could not find component class.");
1820 /* If the component type has not been linked return NULL */
1821 if (comp && !comp->linked)
1824 /* Allocate the arraydescriptor */
1825 desc = NEW(arraydescriptor);
1828 /* c is an array of references */
1829 desc->arraytype = ARRAYTYPE_OBJECT;
1830 desc->componentsize = sizeof(void*);
1831 desc->dataoffset = OFFSET(java_objectarray,data);
1833 compvftbl = comp->vftbl;
1835 panic("Component class has no vftbl");
1836 desc->componentvftbl = compvftbl;
1838 if (compvftbl->arraydesc) {
1839 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1840 if (compvftbl->arraydesc->dimension >= 255)
1841 panic("Creating array of dimension >255");
1842 desc->dimension = compvftbl->arraydesc->dimension + 1;
1843 desc->elementtype = compvftbl->arraydesc->elementtype;
1846 desc->elementvftbl = compvftbl;
1847 desc->dimension = 1;
1848 desc->elementtype = ARRAYTYPE_OBJECT;
1852 /* c is an array of a primitive type */
1853 switch (c->name->text[1]) {
1854 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1855 desc->dataoffset = OFFSET(java_booleanarray,data);
1856 desc->componentsize = sizeof(u1);
1859 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1860 desc->dataoffset = OFFSET(java_bytearray,data);
1861 desc->componentsize = sizeof(u1);
1864 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1865 desc->dataoffset = OFFSET(java_chararray,data);
1866 desc->componentsize = sizeof(u2);
1869 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1870 desc->dataoffset = OFFSET(java_doublearray,data);
1871 desc->componentsize = sizeof(double);
1874 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1875 desc->dataoffset = OFFSET(java_floatarray,data);
1876 desc->componentsize = sizeof(float);
1879 case 'I': desc->arraytype = ARRAYTYPE_INT;
1880 desc->dataoffset = OFFSET(java_intarray,data);
1881 desc->componentsize = sizeof(s4);
1884 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1885 desc->dataoffset = OFFSET(java_longarray,data);
1886 desc->componentsize = sizeof(s8);
1889 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1890 desc->dataoffset = OFFSET(java_shortarray,data);
1891 desc->componentsize = sizeof(s2);
1895 panic("Invalid array class name");
1898 desc->componentvftbl = NULL;
1899 desc->elementvftbl = NULL;
1900 desc->dimension = 1;
1901 desc->elementtype = desc->arraytype;
1908 /********************** Function: class_link ***********************************
1910 Tries to link a class. The super class and every implemented interface must
1911 already have been linked. The function calculates the length in bytes that
1912 an instance of this class requires as well as the VTBL for methods and
1915 If the class can be linked, it is removed from the list 'unlinkedclasses'
1916 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1919 Attention: If cyclical class definitions are encountered, the program gets
1920 into an infinite loop (we'll have to work that out)
1922 *******************************************************************************/
1924 void class_link(classinfo *c)
1926 s4 supervftbllength; /* vftbllegnth of super class */
1927 s4 vftbllength; /* vftbllength of current class */
1928 s4 interfacetablelength; /* interface table length */
1929 classinfo *super = c->super; /* super class */
1930 classinfo *ic, *c2; /* intermediate class variables */
1931 vftbl *v; /* vftbl of current class */
1932 s4 i; /* interface/method/field counter */
1933 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1936 /* check if all superclasses are already linked, if not put c at end of
1937 unlinked list and return. Additionally initialize class fields. */
1939 /* check interfaces */
1941 for (i = 0; i < c->interfacescount; i++) {
1942 ic = c->interfaces[i];
1944 list_remove(&unlinkedclasses, c);
1945 list_addlast(&unlinkedclasses, c);
1950 /* check super class */
1952 if (super == NULL) { /* class java.long.Object */
1954 c->classUsed = USED; /* Object class is always used CO-RT*/
1956 c->instancesize = sizeof(java_objectheader);
1958 vftbllength = supervftbllength = 0;
1960 c->finalizer = NULL;
1963 if (!super->linked) {
1964 list_remove(&unlinkedclasses, c);
1965 list_addlast(&unlinkedclasses, c);
1969 /* handle array classes */
1970 /* The component class must have been linked already. */
1971 if (c->name->text[0] == '[')
1972 if ((arraydesc = class_link_array(c)) == NULL) {
1973 list_remove(&unlinkedclasses, c);
1974 list_addlast(&unlinkedclasses, c);
1978 /* Don't allow extending final classes */
1979 if ((super->flags & ACC_FINAL) != 0)
1980 panic("Trying to extend final class");
1982 if (c->flags & ACC_INTERFACE)
1983 c->index = interfaceindex++;
1985 c->index = super->index + 1;
1987 c->instancesize = super->instancesize;
1989 vftbllength = supervftbllength = super->vftbl->vftbllength;
1991 c->finalizer = super->finalizer;
1996 char logtext[MAXLOGTEXT];
1997 sprintf(logtext, "Linking Class: ");
1998 utf_sprint(logtext + strlen(logtext), c->name );
2002 /* compute vftbl length */
2004 for (i = 0; i < c->methodscount; i++) {
2005 methodinfo *m = &(c->methods[i]);
2007 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2008 classinfo *sc = super;
2011 for (j = 0; j < sc->methodscount; j++) {
2012 if (method_canoverwrite(m, &(sc->methods[j]))) {
2013 if ((sc->methods[j].flags & ACC_FINAL) != 0)
2014 panic("Trying to overwrite final method");
2015 m->vftblindex = sc->methods[j].vftblindex;
2016 goto foundvftblindex;
2021 m->vftblindex = (vftbllength++);
2027 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2030 /* compute interfacetable length */
2032 interfacetablelength = 0;
2035 for (i = 0; i < c2->interfacescount; i++) {
2036 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2037 if (h > interfacetablelength)
2038 interfacetablelength = h;
2043 /* allocate virtual function table */
2045 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2046 (vftbllength - 1) + sizeof(methodptr*) *
2047 (interfacetablelength - (interfacetablelength > 0)));
2048 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2049 (interfacetablelength > 1));
2050 c->header.vftbl = c->vftbl = v;
2052 v->vftbllength = vftbllength;
2053 v->interfacetablelength = interfacetablelength;
2054 v->arraydesc = arraydesc;
2056 /* store interface index in vftbl */
2057 if (c->flags & ACC_INTERFACE)
2058 v->baseval = -(c->index);
2060 /* copy virtual function table of super class */
2062 for (i = 0; i < supervftbllength; i++)
2063 v->table[i] = super->vftbl->table[i];
2065 /* add method stubs into virtual function table */
2067 for (i = 0; i < c->methodscount; i++) {
2068 methodinfo *m = &(c->methods[i]);
2069 if (!(m->flags & ACC_STATIC)) {
2070 v->table[m->vftblindex] = m->stubroutine;
2074 /* compute instance size and offset of each field */
2076 for (i = 0; i < c->fieldscount; i++) {
2078 fieldinfo *f = &(c->fields[i]);
2080 if (!(f->flags & ACC_STATIC) ) {
2081 dsize = desc_typesize(f->descriptor);
2082 c->instancesize = ALIGN(c->instancesize, dsize);
2083 f->offset = c->instancesize;
2084 c->instancesize += dsize;
2088 /* initialize interfacetable and interfacevftbllength */
2090 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2093 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2096 for (i = 0; i < interfacetablelength; i++) {
2097 v->interfacevftbllength[i] = 0;
2098 v->interfacetable[-i] = NULL;
2101 /* add interfaces */
2103 for (c2 = c; c2 != NULL; c2 = c2->super)
2104 for (i = 0; i < c2->interfacescount; i++) {
2105 class_addinterface(c, c2->interfaces[i]);
2108 /* add finalizer method (not for java.lang.Object) */
2110 if (super != NULL) {
2112 static utf *finame = NULL;
2113 static utf *fidesc = NULL;
2116 finame = utf_finalize;
2118 fidesc = utf_fidesc;
2120 fi = class_findmethod(c, finame, fidesc);
2122 if (!(fi->flags & ACC_STATIC)) {
2132 list_remove(&unlinkedclasses, c);
2133 list_addlast(&linkedclasses, c);
2137 /******************* Function: class_freepool **********************************
2139 Frees all resources used by this classes Constant Pool.
2141 *******************************************************************************/
2143 static void class_freecpool (classinfo *c)
2149 for (idx=0; idx < c->cpcount; idx++) {
2150 tag = c->cptags[idx];
2151 info = c->cpinfos[idx];
2155 case CONSTANT_Fieldref:
2156 case CONSTANT_Methodref:
2157 case CONSTANT_InterfaceMethodref:
2158 FREE (info, constant_FMIref);
2160 case CONSTANT_Integer:
2161 FREE (info, constant_integer);
2163 case CONSTANT_Float:
2164 FREE (info, constant_float);
2167 FREE (info, constant_long);
2169 case CONSTANT_Double:
2170 FREE (info, constant_double);
2172 case CONSTANT_NameAndType:
2173 FREE (info, constant_nameandtype);
2179 MFREE (c -> cptags, u1, c -> cpcount);
2180 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2184 /*********************** Function: class_free **********************************
2186 Frees all resources used by the class.
2188 *******************************************************************************/
2190 static void class_free(classinfo *c)
2197 MFREE(c->interfaces, classinfo*, c->interfacescount);
2199 for (i = 0; i < c->fieldscount; i++)
2200 field_free(&(c->fields[i]));
2202 for (i = 0; i < c->methodscount; i++)
2203 method_free(&(c->methods[i]));
2204 MFREE(c->methods, methodinfo, c->methodscount);
2206 if ((v = c->vftbl) != NULL) {
2208 mem_free(v->arraydesc,sizeof(arraydescriptor));
2210 for (i = 0; i < v->interfacetablelength; i++) {
2211 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2213 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2215 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2216 sizeof(methodptr*) * (v->interfacetablelength -
2217 (v->interfacetablelength > 0));
2218 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2219 (v->interfacetablelength > 1));
2223 if (c->innerclasscount)
2224 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2226 /* if (c->classvftbl)
2227 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2233 /************************* Function: class_findfield ***************************
2235 Searches a 'classinfo' structure for a field having the given name and
2238 *******************************************************************************/
2240 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2244 for (i = 0; i < c->fieldscount; i++) {
2245 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2246 return &(c->fields[i]);
2249 panic("Can not find field given in CONSTANT_Fieldref");
2251 /* keep compiler happy */
2256 /************************* Function: class_findmethod **************************
2258 Searches a 'classinfo' structure for a method having the given name and
2259 type and returns the index in the class info structure.
2260 If type is NULL, it is ignored.
2262 *******************************************************************************/
2264 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2267 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2269 int buffer_len, pos;
2271 #ifdef JOWENN_DEBUG1
2274 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2276 buffer = MNEW(char, buffer_len);
2278 strcpy(buffer, "class_findmethod: method:");
2279 utf_sprint(buffer + strlen(buffer), name);
2280 strcpy(buffer + strlen(buffer), ", desc: ");
2281 utf_sprint(buffer + strlen(buffer), desc);
2282 strcpy(buffer + strlen(buffer), ", classname: ");
2283 utf_sprint(buffer + strlen(buffer), c->name);
2287 MFREE(buffer, char, buffer_len);
2289 for (i = 0; i < c->methodscount; i++) {
2290 #ifdef JOWENN_DEBUG2
2292 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2294 buffer = MNEW(char, buffer_len);
2296 strcpy(buffer, "class_findmethod: comparing to method:");
2297 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2298 strcpy(buffer + strlen(buffer), ", desc: ");
2299 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2303 MFREE(buffer, char, buffer_len);
2307 if ((c->methods[i].name == name) && ((desc == NULL) ||
2308 (c->methods[i].descriptor == desc))) {
2313 #ifdef JOWENN_DEBUG2
2314 class_showconstantpool(c);
2315 log_text("class_findmethod: returning NULL");
2322 /************************* Function: class_findmethod **************************
2324 Searches a 'classinfo' structure for a method having the given name and
2326 If type is NULL, it is ignored.
2328 *******************************************************************************/
2330 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2334 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2336 int buffer_len, pos;
2338 #ifdef JOWENN_DEBUG1
2341 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2343 buffer = MNEW(char, buffer_len);
2345 strcpy(buffer, "class_findmethod: method:");
2346 utf_sprint(buffer + strlen(buffer), name);
2347 strcpy(buffer + strlen(buffer), ", desc: ");
2348 utf_sprint(buffer + strlen(buffer), desc);
2349 strcpy(buffer + strlen(buffer), ", classname: ");
2350 utf_sprint(buffer + strlen(buffer), c->name);
2354 MFREE(buffer, char, buffer_len);
2356 for (i = 0; i < c->methodscount; i++) {
2357 #ifdef JOWENN_DEBUG2
2359 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2361 buffer = MNEW(char, buffer_len);
2363 strcpy(buffer, "class_findmethod: comparing to method:");
2364 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2365 strcpy(buffer + strlen(buffer), ", desc: ");
2366 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2370 MFREE(buffer, char, buffer_len);
2373 if ((c->methods[i].name == name) && ((desc == NULL) ||
2374 (c->methods[i].descriptor == desc))) {
2375 return &(c->methods[i]);
2378 #ifdef JOWENN_DEBUG2
2379 class_showconstantpool(c);
2380 log_text("class_findmethod: returning NULL");
2385 s4 idx=class_findmethodIndex(c, name, desc);
2386 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2387 if (idx == -1) return NULL;
2389 return &(c->methods[idx]);
2393 /*********************** Function: class_fetchmethod **************************
2395 like class_findmethod, but aborts with an error if the method is not found
2397 *******************************************************************************/
2399 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2402 mi = class_findmethod(c, name, desc);
2405 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2406 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2407 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2408 panic("Method not found");
2415 /************************* Function: class_findmethod_approx ******************
2417 like class_findmethod but ignores the return value when comparing the
2420 *******************************************************************************/
2422 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2426 for (i = 0; i < c->methodscount; i++) {
2427 if (c->methods[i].name == name) {
2428 utf *meth_descr = c->methods[i].descriptor;
2432 return &(c->methods[i]);
2434 if (desc->blength <= meth_descr->blength) {
2435 /* current position in utf text */
2436 char *desc_utf_ptr = desc->text;
2437 char *meth_utf_ptr = meth_descr->text;
2438 /* points behind utf strings */
2439 char *desc_end = utf_end(desc);
2440 char *meth_end = utf_end(meth_descr);
2443 /* compare argument types */
2444 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2446 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2447 break; /* no match */
2450 return &(c->methods[i]); /* all parameter types equal */
2460 /***************** Function: class_resolvemethod_approx ***********************
2462 Searches a class and every super class for a method (without paying
2463 attention to the return value)
2465 *******************************************************************************/
2467 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2470 /* search for method (ignore returntype) */
2471 methodinfo *m = class_findmethod_approx(c, name, desc);
2474 /* search superclass */
2482 /************************* Function: class_resolvemethod ***********************
2484 Searches a class and every super class for a method.
2486 *******************************************************************************/
2488 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2491 methodinfo *m = class_findmethod(c, name, desc);
2493 /* search superclass */
2501 /************************* Function: class_issubclass **************************
2503 Checks if sub is a descendant of super.
2505 *******************************************************************************/
2507 bool class_issubclass(classinfo *sub, classinfo *super)
2510 if (!sub) return false;
2511 if (sub == super) return true;
2517 /****************** Initialization function for classes ******************
2519 In Java, every class can have a static initialization function. This
2520 function has to be called BEFORE calling other methods or accessing static
2523 *******************************************************************************/
2525 void class_init(classinfo *c)
2533 if (!makeinitializations)
2538 c->initialized = true;
2541 count_class_inits++;
2545 class_init(c->super);
2546 for (i = 0; i < c->interfacescount; i++)
2547 class_init(c->interfaces[i]); /* real */
2549 m = class_findmethod(c, utf_clinit, utf_fidesc);
2552 char logtext[MAXLOGTEXT];
2553 sprintf(logtext, "Class ");
2554 utf_sprint(logtext + strlen(logtext), c->name);
2555 sprintf(logtext + strlen(logtext), " has no initializer");
2558 /* goto callinitialize;*/
2562 if (!(m->flags & ACC_STATIC))
2563 panic("Class initializer is not static!");
2566 char logtext[MAXLOGTEXT];
2567 sprintf(logtext, "Starting initializer for class: ");
2568 utf_sprint(logtext + strlen(logtext), c->name);
2577 /* now call the initializer */
2578 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2581 assert(blockInts == 0);
2585 /* we have to throw an exception */
2587 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2588 printf("Caused by: ");
2589 utf_display(exceptionptr->vftbl->class->name);
2596 char logtext[MAXLOGTEXT];
2597 sprintf(logtext, "Finished initializer for class: ");
2598 utf_sprint(logtext + strlen(logtext), c->name);
2602 if (c->name == utf_systemclass) {
2603 /* class java.lang.System requires explicit initialization */
2606 printf("#### Initializing class System");
2608 /* find initializing method */
2609 m = class_findmethod(c,
2610 utf_initsystemclass,
2614 /* no method found */
2615 /* printf("initializeSystemClass failed"); */
2624 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2627 assert(blockInts == 0);
2632 printf("#### initializeSystemClass has thrown: ");
2633 utf_display(exceptionptr->vftbl->class->name);
2641 /********* Function: find_class_method_constant *********/
2643 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2648 for (i=0; i<c->cpcount; i++) {
2650 e = c -> cpinfos [i];
2653 switch (c -> cptags [i]) {
2654 case CONSTANT_Methodref:
2656 constant_FMIref *fmi = e;
2657 if ( (fmi->class->name == c1)
2658 && (fmi->name == m1)
2659 && (fmi->descriptor == d1)) {
2666 case CONSTANT_InterfaceMethodref:
2668 constant_FMIref *fmi = e;
2669 if ( (fmi->class->name == c1)
2670 && (fmi->name == m1)
2671 && (fmi->descriptor == d1)) {
2685 void class_showconstanti(classinfo *c, int ii)
2691 printf ("#%d: ", (int) i);
2693 switch (c->cptags [i]) {
2694 case CONSTANT_Class:
2695 printf("Classreference -> ");
2696 utf_display(((classinfo*)e)->name);
2699 case CONSTANT_Fieldref:
2700 printf("Fieldref -> "); goto displayFMIi;
2701 case CONSTANT_Methodref:
2702 printf("Methodref -> "); goto displayFMIi;
2703 case CONSTANT_InterfaceMethodref:
2704 printf("InterfaceMethod -> "); goto displayFMIi;
2707 constant_FMIref *fmi = e;
2708 utf_display(fmi->class->name);
2710 utf_display(fmi->name);
2712 utf_display(fmi->descriptor);
2716 case CONSTANT_String:
2717 printf("String -> ");
2720 case CONSTANT_Integer:
2721 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2723 case CONSTANT_Float:
2724 printf("Float -> %f", ((constant_float*)e)->value);
2726 case CONSTANT_Double:
2727 printf("Double -> %f", ((constant_double*)e)->value);
2731 u8 v = ((constant_long*)e)->value;
2733 printf("Long -> %ld", (long int) v);
2735 printf("Long -> HI: %ld, LO: %ld\n",
2736 (long int) v.high, (long int) v.low);
2740 case CONSTANT_NameAndType:
2742 constant_nameandtype *cnt = e;
2743 printf("NameAndType: ");
2744 utf_display(cnt->name);
2746 utf_display(cnt->descriptor);
2754 panic("Invalid type of ConstantPool-Entry");
2761 void class_showconstantpool (classinfo *c)
2766 printf ("---- dump of constant pool ----\n");
2768 for (i=0; i<c->cpcount; i++) {
2769 printf ("#%d: ", (int) i);
2771 e = c -> cpinfos [i];
2774 switch (c -> cptags [i]) {
2775 case CONSTANT_Class:
2776 printf ("Classreference -> ");
2777 utf_display ( ((classinfo*)e) -> name );
2780 case CONSTANT_Fieldref:
2781 printf ("Fieldref -> "); goto displayFMI;
2782 case CONSTANT_Methodref:
2783 printf ("Methodref -> "); goto displayFMI;
2784 case CONSTANT_InterfaceMethodref:
2785 printf ("InterfaceMethod -> "); goto displayFMI;
2788 constant_FMIref *fmi = e;
2789 utf_display ( fmi->class->name );
2791 utf_display ( fmi->name);
2793 utf_display ( fmi->descriptor );
2797 case CONSTANT_String:
2798 printf ("String -> ");
2801 case CONSTANT_Integer:
2802 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2804 case CONSTANT_Float:
2805 printf ("Float -> %f", ((constant_float*)e) -> value);
2807 case CONSTANT_Double:
2808 printf ("Double -> %f", ((constant_double*)e) -> value);
2812 u8 v = ((constant_long*)e) -> value;
2814 printf ("Long -> %ld", (long int) v);
2816 printf ("Long -> HI: %ld, LO: %ld\n",
2817 (long int) v.high, (long int) v.low);
2821 case CONSTANT_NameAndType:
2823 constant_nameandtype *cnt = e;
2824 printf ("NameAndType: ");
2825 utf_display (cnt->name);
2827 utf_display (cnt->descriptor);
2831 printf ("Utf8 -> ");
2835 panic ("Invalid type of ConstantPool-Entry");
2845 /********** Function: class_showmethods (debugging only) *************/
2847 void class_showmethods (classinfo *c)
2851 printf ("--------- Fields and Methods ----------------\n");
2852 printf ("Flags: "); printflags (c->flags); printf ("\n");
2854 printf ("This: "); utf_display (c->name); printf ("\n");
2856 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2858 printf ("Index: %d\n", c->index);
2860 printf ("interfaces:\n");
2861 for (i=0; i < c-> interfacescount; i++) {
2863 utf_display (c -> interfaces[i] -> name);
2864 printf (" (%d)\n", c->interfaces[i] -> index);
2867 printf ("fields:\n");
2868 for (i=0; i < c -> fieldscount; i++) {
2869 field_display (&(c -> fields[i]));
2872 printf ("methods:\n");
2873 for (i=0; i < c -> methodscount; i++) {
2874 methodinfo *m = &(c->methods[i]);
2875 if ( !(m->flags & ACC_STATIC))
2876 printf ("vftblindex: %d ", m->vftblindex);
2878 method_display ( m );
2882 printf ("Virtual function table:\n");
2883 for (i=0; i<c->vftbl->vftbllength; i++) {
2884 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2891 /******************************************************************************/
2892 /******************* General functions for the class loader *******************/
2893 /******************************************************************************/
2895 /********************* Function: loader_load ***********************************
2897 Loads and links the class desired class and each class and interface
2899 Returns: a pointer to this class
2901 *******************************************************************************/
2903 static int loader_load_running = 0;
2905 classinfo *loader_load(utf *topname)
2911 classinfo *notlinkable;
2913 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2914 pthread_mutex_lock(&compiler_mutex);
2917 /* avoid recursive calls */
2918 if (loader_load_running)
2919 return class_new(topname);
2921 loader_load_running++;
2926 starttime = getcputime();
2928 top = class_new(topname);
2931 while ((c = list_first(&unloadedclasses))) {
2932 if (!class_load(c)) {
2934 dolog("Failed to load class");
2935 list_remove(&unloadedclasses, c);
2942 dolog("Linking...");
2944 /* XXX added a hack to break infinite linking loops. A better
2945 * linking algorithm would be nice. -Edwin */
2947 while ((c = list_first(&unlinkedclasses))) {
2952 else if (notlinkable == c) {
2953 /* We tried to link this class for the second time and
2954 * no other classes were linked in between, so we are
2958 dolog("Cannot resolve linking dependencies");
2961 throw_linkageerror_message(c->name);
2969 dolog("Linking done.");
2972 loader_compute_subclasses();
2975 if (getloadingtime) {
2976 stoptime = getcputime();
2977 loadingtime += (stoptime - starttime);
2981 loader_load_running--;
2983 /* check if a former loader_load call tried to load/link the class and
2984 failed. This is needed because the class didn't appear in the
2985 undloadclasses or unlinkedclasses list during this class. */
2988 if (linkverbose) dolog("Failed to load class (former call)");
2989 throw_noclassdeffounderror_message(top->name);
2992 } else if (!top->linked) {
2994 dolog("Failed to link class (former call)");
2995 throw_linkageerror_message(top->name);
3002 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3003 pthread_mutex_unlock(&compiler_mutex);
3006 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
3012 /****************** Function: loader_load_sysclass ****************************
3014 Loads and links the class desired class and each class and interface
3017 The pointer to the classinfo is stored in *top if top != NULL.
3018 The pointer is also returned.
3020 If the class could not be loaded the function aborts with an error.
3022 *******************************************************************************/
3024 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3028 if ((cls = loader_load(topname)) == NULL) {
3029 log_plain("Could not load important system class: ");
3030 log_plain_utf(topname);
3032 panic("Could not load important system class");
3035 if (top) *top = cls;
3041 /**************** function: create_primitive_classes ***************************
3043 create classes representing primitive types
3045 ********************************************************************************/
3048 void create_primitive_classes()
3052 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3053 /* create primitive class */
3054 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3055 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3056 c -> impldBy = NULL;
3058 /* prevent loader from loading primitive class */
3059 list_remove (&unloadedclasses, c);
3061 /* add to unlinked classes */
3062 list_addlast (&unlinkedclasses, c);
3063 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3066 primitivetype_table[i].class_primitive = c;
3068 /* create class for wrapping the primitive type */
3069 primitivetype_table[i].class_wrap =
3070 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3071 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3072 primitivetype_table[i].class_wrap -> impldBy = NULL;
3074 /* create the primitive array class */
3075 if (primitivetype_table[i].arrayname) {
3076 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3077 primitivetype_table[i].arrayclass = c;
3079 if (!c->linked) class_link(c);
3080 primitivetype_table[i].arrayvftbl = c->vftbl;
3085 /**************** function: class_primitive_from_sig ***************************
3087 return the primitive class indicated by the given signature character
3089 If the descriptor does not indicate a valid primitive type the
3090 return value is NULL.
3092 ********************************************************************************/
3094 classinfo *class_primitive_from_sig(char sig)
3097 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3098 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3099 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3100 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3101 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3102 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3103 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3104 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3105 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3110 /****************** function: class_from_descriptor ****************************
3112 return the class indicated by the given descriptor
3114 utf_ptr....first character of descriptor
3115 end_ptr....first character after the end of the string
3116 next.......if non-NULL, *next is set to the first character after
3117 the descriptor. (Undefined if an error occurs.)
3119 mode.......a combination (binary or) of the following flags:
3121 (Flags marked with * are the default settings.)
3123 What to do if a reference type descriptor is parsed successfully:
3125 CLASSLOAD_SKIP...skip it and return something != NULL
3126 * CLASSLOAD_NEW....get classinfo * via class_new
3127 CLASSLOAD_LOAD...get classinfo * via loader_load
3129 How to handle primitive types:
3131 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3132 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3134 How to handle "V" descriptors:
3136 * CLASSLOAD_VOID.....handle it like other primitive types
3137 CLASSLOAD_NOVOID...treat it as an error
3139 How to deal with extra characters after the end of the
3142 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3143 CLASSLOAD_CHECKEND.....treat them as an error
3145 How to deal with errors:
3147 * CLASSLOAD_PANIC....abort execution with an error message
3148 CLASSLOAD_NOPANIC..return NULL on error
3150 ********************************************************************************/
3152 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3153 char **next, int mode)
3155 char *start = utf_ptr;
3159 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3161 if (mode & CLASSLOAD_CHECKEND)
3162 error |= (utf_ptr != end_ptr);
3165 if (next) *next = utf_ptr;
3169 if (mode & CLASSLOAD_NOVOID)
3180 return (mode & CLASSLOAD_NULLPRIMITIVE)
3182 : class_primitive_from_sig(*start);
3189 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3190 name = utf_new(start,utf_ptr-start);
3191 return (mode & CLASSLOAD_LOAD)
3192 ? loader_load(name) : class_new(name); /* XXX */
3196 /* An error occurred */
3197 if (mode & CLASSLOAD_NOPANIC)
3200 log_plain("Invalid descriptor at beginning of '");
3201 log_plain_utf(utf_new(start, end_ptr-start));
3205 panic("Invalid descriptor");
3207 /* keep compiler happy */
3212 /******************* function: type_from_descriptor ****************************
3214 return the basic type indicated by the given descriptor
3216 This function parses a descriptor and returns its basic type as
3217 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3219 cls...if non-NULL the referenced variable is set to the classinfo *
3220 returned by class_from_descriptor.
3222 For documentation of the arguments utf_ptr, end_ptr, next and mode
3223 see class_from_descriptor. The only difference is that
3224 type_from_descriptor always uses CLASSLOAD_PANIC.
3226 ********************************************************************************/
3228 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3229 char **next, int mode)
3232 if (!cls) cls = &mycls;
3233 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3250 return TYPE_ADDRESS;
3254 /*************** function: create_pseudo_classes *******************************
3256 create pseudo classes used by the typechecker
3258 ********************************************************************************/
3260 static void create_pseudo_classes()
3262 /* pseudo class for Arraystubs (extends java.lang.Object) */
3264 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3265 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3267 pseudo_class_Arraystub->super = class_java_lang_Object;
3268 pseudo_class_Arraystub->interfacescount = 2;
3269 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3270 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3271 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3273 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3274 class_link(pseudo_class_Arraystub);
3276 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3278 /* pseudo class representing the null type */
3280 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3281 list_remove(&unloadedclasses, pseudo_class_Null);
3283 pseudo_class_Null->super = class_java_lang_Object;
3285 list_addlast(&unlinkedclasses, pseudo_class_Null);
3286 class_link(pseudo_class_Null);
3288 /* pseudo class representing new uninitialized objects */
3290 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3291 list_remove(&unloadedclasses, pseudo_class_New);
3293 pseudo_class_New->super = class_java_lang_Object;
3295 list_addlast(&unlinkedclasses, pseudo_class_New);
3296 class_link(pseudo_class_New);
3300 /********************** Function: loader_init **********************************
3302 Initializes all lists and loads all classes required for the system or the
3305 *******************************************************************************/
3307 void loader_init(u1 *stackbottom)
3311 log_text("Entering loader_init");
3313 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3314 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3315 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3317 /* create utf-symbols for pointer comparison of frequently used strings */
3318 utf_innerclasses = utf_new_char("InnerClasses");
3319 utf_constantvalue = utf_new_char("ConstantValue");
3320 utf_code = utf_new_char("Code");
3321 utf_finalize = utf_new_char("finalize");
3322 utf_fidesc = utf_new_char("()V");
3323 utf_clinit = utf_new_char("<clinit>");
3324 utf_initsystemclass = utf_new_char("initializeSystemClass");
3325 utf_systemclass = utf_new_char("java/lang/System");
3326 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3327 utf_initialize = utf_new_char("initialize");
3328 utf_initializedesc = utf_new_char("(I)V");
3330 utf_vmclass = utf_new_char("java/lang/VMClass");
3332 /* create some important classes */
3333 /* These classes have to be created now because the classinfo
3334 * pointers are used in the loading code.
3336 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3337 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3338 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3339 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3341 log_text("loader_init: java/lang/Object");
3342 /* load the classes which were created above */
3343 loader_load_sysclass(NULL, class_java_lang_Object->name);
3345 loader_inited = 1; /*JOWENN*/
3347 loader_load_sysclass(&class_java_lang_Throwable,
3348 utf_new_char("java/lang/Throwable"));
3350 log_text("loader_init: loader_load: java/lang/ClassCastException");
3351 loader_load_sysclass(&class_java_lang_ClassCastException,
3352 utf_new_char ("java/lang/ClassCastException"));
3353 loader_load_sysclass(&class_java_lang_NullPointerException,
3354 utf_new_char ("java/lang/NullPointerException"));
3355 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3356 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3357 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3358 utf_new_char ("java/lang/NegativeArraySizeException"));
3359 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3360 utf_new_char ("java/lang/OutOfMemoryError"));
3361 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3362 utf_new_char ("java/lang/ArrayStoreException"));
3363 loader_load_sysclass(&class_java_lang_ArithmeticException,
3364 utf_new_char ("java/lang/ArithmeticException"));
3365 loader_load_sysclass(&class_java_lang_ThreadDeath,
3366 utf_new_char ("java/lang/ThreadDeath"));
3368 /* create classes representing primitive types */
3369 create_primitive_classes();
3371 /* create classes used by the typechecker */
3372 create_pseudo_classes();
3374 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3375 stringtable_update();
3382 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3383 proto_java_lang_ClassCastException =
3384 builtin_new(class_java_lang_ClassCastException);
3386 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3388 proto_java_lang_NullPointerException =
3389 builtin_new(class_java_lang_NullPointerException);
3390 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3392 proto_java_lang_ArrayIndexOutOfBoundsException =
3393 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3395 proto_java_lang_NegativeArraySizeException =
3396 builtin_new(class_java_lang_NegativeArraySizeException);
3398 proto_java_lang_OutOfMemoryError =
3399 builtin_new(class_java_lang_OutOfMemoryError);
3401 proto_java_lang_ArithmeticException =
3402 builtin_new(class_java_lang_ArithmeticException);
3404 proto_java_lang_ArrayStoreException =
3405 builtin_new(class_java_lang_ArrayStoreException);
3407 proto_java_lang_ThreadDeath =
3408 builtin_new(class_java_lang_ThreadDeath);
3414 /********************* Function: loader_initclasses ****************************
3416 Initializes all loaded but uninitialized classes
3418 *******************************************************************************/
3421 /* XXX TWISTI: i think we do not need this */
3422 void loader_initclasses ()
3426 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3427 pthread_mutex_lock(&compiler_mutex);
3430 intsDisable(); /* schani */
3432 if (makeinitializations) {
3433 c = list_first(&linkedclasses);
3436 c = list_next(&linkedclasses, c);
3440 intsRestore(); /* schani */
3442 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3443 pthread_mutex_unlock(&compiler_mutex);
3449 static void loader_compute_class_values(classinfo *c)
3453 c->vftbl->baseval = ++classvalue;
3456 while (subs != NULL) {
3457 loader_compute_class_values(subs);
3458 subs = subs->nextsub;
3460 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3465 for (i = 0; i < c->index; i++)
3467 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3468 utf_display(c->name);
3475 void loader_compute_subclasses()
3479 intsDisable(); /* schani */
3481 c = list_first(&linkedclasses);
3483 if (!(c->flags & ACC_INTERFACE)) {
3487 c = list_next(&linkedclasses, c);
3490 c = list_first(&linkedclasses);
3492 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3493 c->nextsub = c->super->sub;
3496 c = list_next(&linkedclasses, c);
3500 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3503 loader_compute_class_values(class_java_lang_Object);
3504 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3508 intsRestore(); /* schani */
3512 /******************** function classloader_buffer ******************************
3514 sets buffer for reading classdata
3516 *******************************************************************************/
3518 void classload_buffer(u1 *buf, int len)
3521 classbuffer_size = len;
3522 classbuf_pos = buf - 1;
3526 /******************** Function: loader_close ***********************************
3530 *******************************************************************************/
3536 while ((c = list_first(&unloadedclasses))) {
3537 list_remove(&unloadedclasses, c);
3540 while ((c = list_first(&unlinkedclasses))) {
3541 list_remove(&unlinkedclasses, c);
3544 while ((c = list_first(&linkedclasses))) {
3545 list_remove(&linkedclasses, c);
3552 * These are local overrides for various environment variables in Emacs.
3553 * Please do not remove this and leave it at the end of the file, where
3554 * Emacs will automagically detect them.
3555 * ---------------------------------------------------------------------
3558 * indent-tabs-mode: t