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 868 2004-01-10 20:12:10Z 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_init; /* <init> */
91 static utf *utf_clinit; /* <clinit> */
92 static utf *utf_initsystemclass; /* initializeSystemClass */
93 static utf *utf_systemclass; /* java/lang/System */
94 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
95 static utf *utf_vmclass; /* java/lang/VMClassLoader */
96 static utf *utf_initialize;
97 static utf *utf_initializedesc;
98 static utf *utf_java_lang_Object; /* java/lang/Object */
111 /* important system classes ***************************************************/
113 classinfo *class_java_lang_Object;
114 classinfo *class_java_lang_String;
116 classinfo *class_java_lang_Throwable;
117 classinfo *class_java_lang_Cloneable;
118 classinfo *class_java_io_Serializable;
120 /* Pseudo classes for the typechecker */
121 classinfo *pseudo_class_Arraystub = NULL;
122 classinfo *pseudo_class_Null = NULL;
123 classinfo *pseudo_class_New = NULL;
124 vftbl *pseudo_class_Arraystub_vftbl = NULL;
127 /* These are made static so they cannot be used for throwing in native */
129 static classinfo *class_java_lang_ClassCastException;
130 static classinfo *class_java_lang_NullPointerException;
131 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
132 static classinfo *class_java_lang_NegativeArraySizeException;
133 static classinfo *class_java_lang_OutOfMemoryError;
134 static classinfo *class_java_lang_ArithmeticException;
135 static classinfo *class_java_lang_ArrayStoreException;
136 static classinfo *class_java_lang_ThreadDeath;
138 static int loader_inited = 0;
141 /********************************************************************
142 list of classpath entries (either filesystem directories or
144 ********************************************************************/
145 static classpath_info *classpath_entries=0;
148 /******************************************************************************
150 structure for primitive classes: contains the class for wrapping the
151 primitive type, the primitive class, the name of the class for wrapping,
152 the one character type signature and the name of the primitive class
154 ******************************************************************************/
156 /* CAUTION: Don't change the order of the types. This table is indexed
157 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
159 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
160 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
161 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
162 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
163 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
164 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
165 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
166 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
167 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
168 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
172 /* instances of important system classes **************************************/
174 java_objectheader *proto_java_lang_ClassCastException;
175 java_objectheader *proto_java_lang_NullPointerException;
176 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
177 java_objectheader *proto_java_lang_NegativeArraySizeException;
178 java_objectheader *proto_java_lang_OutOfMemoryError;
179 java_objectheader *proto_java_lang_ArithmeticException;
180 java_objectheader *proto_java_lang_ArrayStoreException;
181 java_objectheader *proto_java_lang_ThreadDeath;
183 /************* functions for reading classdata *********************************
185 getting classdata in blocks of variable size
186 (8,16,32,64-bit integer or float)
188 *******************************************************************************/
190 static char *classpath = ""; /* searchpath for classfiles */
191 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
192 static u1 *classbuf_pos; /* current position in classfile buffer */
193 static int classbuffer_size; /* size of classfile-data */
195 /* assert that at least <len> bytes are left to read */
196 /* <len> is limited to the range of non-negative s4 values */
197 #define ASSERT_LEFT(len) \
198 do {if ( ((s4)(len)) < 0 \
199 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
200 panic("Unexpected end of classfile"); } while(0)
202 /* transfer block of classfile data into a buffer */
204 #define suck_nbytes(buffer,len) \
205 do {ASSERT_LEFT(len); \
206 memcpy(buffer,classbuf_pos+1,len); \
207 classbuf_pos+=len;} while (0)
209 /* skip block of classfile data */
211 #define skip_nbytes(len) \
212 do {ASSERT_LEFT(len); \
213 classbuf_pos+=len;} while(0)
218 return *++classbuf_pos;
222 u1 a=suck_u1(), b=suck_u1();
223 return ((u2)a<<8)+(u2)b;
227 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
228 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
230 #define suck_s8() (s8) suck_u8()
231 #define suck_s2() (s2) suck_u2()
232 #define suck_s4() (s4) suck_u4()
233 #define suck_s1() (s1) suck_u1()
236 /* get u8 from classfile data */
243 return (hi << 32) + lo;
253 /* get float from classfile data */
254 static float suck_float()
261 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
262 memcpy((u1*) (&f), buffer, 4);
264 suck_nbytes((u1*) (&f), 4);
267 PANICIF (sizeof(float) != 4, "Incompatible float-format");
273 /* get double from classfile data */
274 static double suck_double()
281 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
282 memcpy((u1*) (&d), buffer, 8);
284 suck_nbytes((u1*) (&d), 8);
287 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
293 /************************** function suck_init *********************************
295 called once at startup, sets the searchpath for the classfiles
297 *******************************************************************************/
299 void suck_init(char *cpath)
306 union classpath_info *tmp;
307 union classpath_info *insertAfter=0;
312 if (classpath_entries) panic("suck_init should be called only once");
313 for(start=classpath;(*start)!='\0';) {
314 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
317 filenamelen=(end-start);
351 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
352 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
353 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
356 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
357 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
358 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
363 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
365 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
366 strncpy(filename,start,filenamelen);
367 filename[filenamelen+1]='\0';
372 unzFile uf=unzOpen(filename);
374 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
375 tmp->archive.type=CLASSPATH_ARCHIVE;
381 panic("Zip/JAR not supported");
385 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
386 tmp->filepath.type=CLASSPATH_PATH;
387 tmp->filepath.next=0;
388 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
389 filename[filenamelen]='/';
390 filename[filenamelen+1]='\0';
394 tmp->filepath.filename=filename;
395 tmp->filepath.pathlen=filenamelen;
401 insertAfter->filepath.next=tmp;
403 classpath_entries=tmp;
408 if ((*end)==':') start=end+1; else start=end;
411 if (filename!=0) free(filename);
416 /************************** function suck_start ********************************
418 returns true if classbuffer is already loaded or a file for the
419 specified class has succussfully been read in. All directories of
420 the searchpath are used to find the classfile (<classname>.class).
421 Returns false if no classfile is found and writes an error message.
423 *******************************************************************************/
425 bool suck_start(utf *classname)
427 classpath_info *currPos;
430 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
436 if (classbuffer) return true; /* classbuffer is already valid */
438 utf_ptr = classname->text;
439 while (utf_ptr < utf_end(classname)) {
440 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
442 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
444 filename[filenamelen++] = c;
446 strcpy(filename + filenamelen, ".class");
448 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
450 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
451 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
452 unz_file_info file_info;
453 /*log_text("Class found in zip file");*/
454 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
455 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
456 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
457 classbuffer_size = file_info.uncompressed_size;
458 classbuffer = MNEW(u1, classbuffer_size);
459 classbuf_pos = classbuffer - 1;
460 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
461 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
462 unzCloseCurrentFile(currPos->archive.uf);
465 MFREE(classbuffer, u1, classbuffer_size);
466 log_text("Error while unzipping");
468 } else log_text("Error while opening file in archive");
469 } else log_text("Error while retrieving fileinfo");
471 unzCloseCurrentFile(currPos->archive.uf);
475 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
476 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
477 classfile = fopen(currPos->filepath.filename, "r");
478 if (classfile) { /* file exists */
480 /* determine size of classfile */
482 /* dolog("File: %s",filename); */
484 err = stat(currPos->filepath.filename, &buffer);
486 if (!err) { /* read classfile data */
487 classbuffer_size = buffer.st_size;
488 classbuffer = MNEW(u1, classbuffer_size);
489 classbuf_pos = classbuffer - 1;
490 fread(classbuffer, 1, classbuffer_size, classfile);
501 dolog("Warning: Can not open class file '%s'", filename);
508 /************************** function suck_stop *********************************
510 frees memory for buffer with classfile data.
511 Caution: this function may only be called if buffer has been allocated
512 by suck_start with reading a file
514 *******************************************************************************/
518 /* determine amount of classdata not retrieved by suck-operations */
520 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
522 if (classdata_left > 0) {
524 dolog("There are %d extra bytes at end of classfile",
526 /* The JVM spec disallows extra bytes. */
527 panic("Extra bytes at end of classfile");
532 MFREE(classbuffer, u1, classbuffer_size);
537 /******************************************************************************/
538 /******************* Some support functions ***********************************/
539 /******************************************************************************/
541 void fprintflags (FILE *fp, u2 f)
543 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
544 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
545 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
546 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
547 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
548 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
549 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
550 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
551 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
552 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
553 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
557 /********** internal function: printflags (only for debugging) ***************/
559 void printflags(u2 f)
561 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
562 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
563 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
564 if ( f & ACC_STATIC ) printf (" STATIC");
565 if ( f & ACC_FINAL ) printf (" FINAL");
566 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
567 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
568 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
569 if ( f & ACC_NATIVE ) printf (" NATIVE");
570 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
571 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
575 /************************* Function: skipattribute *****************************
577 skips a (1) 'attribute' structure in the class file
579 *******************************************************************************/
581 static void skipattribute()
590 /********************** Function: skipattributebody ****************************
592 skips an attribute after the 16 bit reference to attribute_name has already
595 *******************************************************************************/
597 static void skipattributebody()
605 /************************* Function: skipattributes ****************************
607 skips num attribute structures
609 *******************************************************************************/
611 static void skipattributes(u4 num)
614 for (i = 0; i < num; i++)
619 /******************** function: innerclass_getconstant ************************
621 like class_getconstant, but if cptags is ZERO null is returned
623 *******************************************************************************/
625 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
627 /* invalid position in constantpool */
628 if (pos >= c->cpcount)
629 panic("Attempt to access constant outside range");
631 /* constantpool entry of type 0 */
635 /* check type of constantpool entry */
636 if (c->cptags[pos] != ctype) {
637 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
638 (int) ctype, (int) c->cptags[pos] );
641 return c->cpinfos[pos];
645 /************************ function: attribute_load ****************************
647 read attributes from classfile
649 *******************************************************************************/
651 static void attribute_load(u4 num, classinfo *c)
655 for (i = 0; i < num; i++) {
656 /* retrieve attribute name */
657 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
659 if (aname == utf_innerclasses) {
660 /* innerclasses attribute */
662 if (c->innerclass != NULL)
663 panic("Class has more than one InnerClasses attribute");
665 /* skip attribute length */
667 /* number of records */
668 c->innerclasscount = suck_u2();
669 /* allocate memory for innerclass structure */
670 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
672 for (j = 0; j < c->innerclasscount; j++) {
673 /* The innerclass structure contains a class with an encoded name,
674 its defining scope, its simple name and a bitmask of the access flags.
675 If an inner class is not a member, its outer_class is NULL,
676 if a class is anonymous, its name is NULL. */
678 innerclassinfo *info = c->innerclass + j;
680 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
681 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
682 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
683 info->flags = suck_u2(); /* access_flags bitmask */
687 /* unknown attribute */
694 /******************* function: checkfielddescriptor ****************************
696 checks whether a field-descriptor is valid and aborts otherwise
697 all referenced classes are inserted into the list of unloaded classes
699 *******************************************************************************/
701 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
703 class_from_descriptor(utf_ptr,end_pos,NULL,
705 | CLASSLOAD_NULLPRIMITIVE
707 | CLASSLOAD_CHECKEND);
709 /* XXX use the following if -noverify */
711 char *tstart; /* pointer to start of classname */
713 char *start = utf_ptr;
715 switch (*utf_ptr++) {
729 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
730 panic ("Ill formed descriptor");
734 panic ("Ill formed descriptor");
737 /* exceeding characters */
738 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
743 /******************* function checkmethoddescriptor ****************************
745 checks whether a method-descriptor is valid and aborts otherwise.
746 All referenced classes are inserted into the list of unloaded classes.
748 The number of arguments is returned. A long or double argument is counted
751 *******************************************************************************/
753 static int checkmethoddescriptor (utf *d)
755 char *utf_ptr = d->text; /* current position in utf text */
756 char *end_pos = utf_end(d); /* points behind utf string */
757 int argcount = 0; /* number of arguments */
759 /* method descriptor must start with parenthesis */
760 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
762 /* check arguments */
763 while (utf_ptr != end_pos && *utf_ptr != ')') {
764 /* XXX we cannot count the this argument here because
765 * we don't know if the method is static. */
766 if (*utf_ptr == 'J' || *utf_ptr == 'D')
770 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
772 | CLASSLOAD_NULLPRIMITIVE
776 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
777 utf_ptr++; /* skip ')' */
779 class_from_descriptor(utf_ptr,end_pos,NULL,
781 | CLASSLOAD_NULLPRIMITIVE
782 | CLASSLOAD_CHECKEND);
785 panic("Invalid method descriptor: too many arguments");
789 /* XXX use the following if -noverify */
791 /* XXX check length */
792 /* check arguments */
793 while ((c = *utf_ptr++) != ')') {
810 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
811 panic ("Ill formed method descriptor");
815 panic ("Ill formed methodtype-descriptor");
819 /* check returntype */
821 /* returntype void */
822 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
825 /* treat as field-descriptor */
826 checkfielddescriptor (utf_ptr,end_pos);
831 /***************** Function: print_arraydescriptor ****************************
833 Debugging helper for displaying an arraydescriptor
835 *******************************************************************************/
837 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
840 fprintf(file, "<NULL>");
845 if (desc->componentvftbl) {
846 if (desc->componentvftbl->class)
847 utf_fprint(file, desc->componentvftbl->class->name);
849 fprintf(file, "<no classinfo>");
855 if (desc->elementvftbl) {
856 if (desc->elementvftbl->class)
857 utf_fprint(file, desc->elementvftbl->class->name);
859 fprintf(file, "<no classinfo>");
863 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
864 desc->dataoffset, desc->componentsize);
868 /******************************************************************************/
869 /************************** Functions for fields ****************************/
870 /******************************************************************************/
873 /************************ Function: field_load *********************************
875 Load everything about a class field from the class file and fill a
876 'fieldinfo' structure. For static fields, space in the data segment is
879 *******************************************************************************/
881 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
883 static void field_load(fieldinfo *f, classinfo *c)
887 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
889 f->flags = suck_u2(); /* ACC flags */
890 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
891 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
892 f->type = jtype = desc_to_type(f->descriptor); /* data type */
893 f->offset = 0; /* offset from start of object */
897 /* check flag consistency */
899 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
900 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
901 panic("Field has invalid access flags");
902 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
903 panic("Field is declared final and volatile");
904 if ((c->flags & ACC_INTERFACE) != 0) {
905 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
906 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
907 panic("Interface field is not declared static final public");
908 if ((f->flags & ACC_TRANSIENT) != 0)
909 panic("Interface field declared transient");
914 case TYPE_INT: f->value.i = 0; break;
915 case TYPE_FLOAT: f->value.f = 0.0; break;
916 case TYPE_DOUBLE: f->value.d = 0.0; break;
917 case TYPE_ADDRESS: f->value.a = NULL; break;
920 f->value.l = 0; break;
922 f->value.l.low = 0; f->value.l.high = 0; break;
926 /* read attributes */
928 for (i = 0; i < attrnum; i++) {
931 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
933 if (aname != utf_constantvalue) {
934 /* unknown attribute */
938 /* constant value attribute */
940 if (pindex != field_load_NOVALUE)
941 panic("Field has more than one ConstantValue attribute");
943 /* check attribute length */
945 panic("ConstantValue attribute has invalid length");
947 /* index of value in constantpool */
950 /* initialize field with value from constantpool */
953 constant_integer *ci =
954 class_getconstant(c, pindex, CONSTANT_Integer);
955 f->value.i = ci->value;
961 class_getconstant(c, pindex, CONSTANT_Long);
962 f->value.l = cl->value;
968 class_getconstant(c, pindex, CONSTANT_Float);
969 f->value.f = cf->value;
974 constant_double *cd =
975 class_getconstant(c, pindex, CONSTANT_Double);
976 f->value.d = cd->value;
981 utf *u = class_getconstant(c, pindex, CONSTANT_String);
982 /* create javastring from compressed utf8-string */
983 f->value.a = literalstring_new(u);
988 log_text ("Invalid Constant - Type");
995 /********************** function: field_free **********************************/
997 static void field_free (fieldinfo *f)
1003 /**************** Function: field_display (debugging only) ********************/
1005 void field_display(fieldinfo *f)
1008 printflags(f->flags);
1010 utf_display(f->name);
1012 utf_display(f->descriptor);
1013 printf(" offset: %ld\n", (long int) (f->offset));
1017 /******************************************************************************/
1018 /************************* Functions for methods ******************************/
1019 /******************************************************************************/
1022 /*********************** Function: method_load *********************************
1024 Loads a method from the class file and fills an existing 'methodinfo'
1025 structure. For native methods, the function pointer field is set to the
1026 real function pointer, for JavaVM methods a pointer to the compiler is used
1029 *******************************************************************************/
1031 static void method_load(methodinfo *m, classinfo *c)
1037 count_all_methods++;
1042 m->flags = suck_u2();
1043 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1044 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1045 argcount = checkmethoddescriptor(m->descriptor);
1046 if ((m->flags & ACC_STATIC) == 0)
1047 argcount++; /* count the 'this' argument */
1051 panic("Method has more than 255 arguments");
1053 /* check flag consistency */
1054 /* XXX could check if <clinit> is STATIC */
1055 if (m->name != utf_clinit) {
1056 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1057 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1058 panic("Method has invalid access flags");
1059 if ((m->flags & ACC_ABSTRACT) != 0) {
1060 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1061 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1062 panic("Abstract method has invalid flags set");
1064 if ((c->flags & ACC_INTERFACE) != 0) {
1065 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1066 != (ACC_ABSTRACT | ACC_PUBLIC))
1067 panic("Interface method is not declared abstract and public");
1069 if (m->name == utf_init) {
1070 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1071 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1072 panic("Instance initialization method has invalid flags set");
1078 m->exceptiontable = NULL;
1079 m->entrypoint = NULL;
1081 m->stubroutine = NULL;
1082 m->methodUsed = NOTUSED;
1085 m->subRedefsUsed = 0;
1089 if (!(m->flags & ACC_NATIVE)) {
1090 m->stubroutine = createcompilerstub(m);
1093 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1094 (m->flags & ACC_STATIC) != 0);
1096 m->stubroutine = createnativestub(f, m);
1101 attrnum = suck_u2();
1102 for (i = 0; i < attrnum; i++) {
1105 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1107 if (aname != utf_code) {
1108 skipattributebody();
1112 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1113 panic("Code attribute for native or abstract method");
1116 panic("Method has more than one Code attribute");
1119 m->maxstack = suck_u2();
1120 m->maxlocals = suck_u2();
1121 if (m->maxlocals < argcount)
1122 panic("max_locals is smaller than the number of arguments");
1124 codelen = suck_u4();
1126 panic("bytecode has zero length");
1127 if (codelen > 65536)
1128 panic("bytecode too long");
1129 m->jcodelength = codelen;
1130 m->jcode = MNEW(u1, m->jcodelength);
1131 suck_nbytes(m->jcode, m->jcodelength);
1132 m->exceptiontablelength = suck_u2();
1134 MNEW(exceptiontable, m->exceptiontablelength);
1137 count_vmcode_len += m->jcodelength + 18;
1138 count_extable_len += 8 * m->exceptiontablelength;
1141 for (e = 0; e < m->exceptiontablelength; e++) {
1143 m->exceptiontable[e].startpc = suck_u2();
1144 m->exceptiontable[e].endpc = suck_u2();
1145 m->exceptiontable[e].handlerpc = suck_u2();
1149 m->exceptiontable[e].catchtype = NULL;
1152 m->exceptiontable[e].catchtype =
1153 class_getconstant(c, idx, CONSTANT_Class);
1157 skipattributes(suck_u2());
1161 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1162 panic("Method missing Code attribute");
1166 /********************* Function: method_free ***********************************
1168 frees all memory that was allocated for this method
1170 *******************************************************************************/
1172 static void method_free(methodinfo *m)
1175 MFREE(m->jcode, u1, m->jcodelength);
1177 if (m->exceptiontable)
1178 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1181 CFREE(m->mcode, m->mcodelength);
1183 if (m->stubroutine) {
1184 if (m->flags & ACC_NATIVE) {
1185 removenativestub(m->stubroutine);
1188 removecompilerstub(m->stubroutine);
1194 /************** Function: method_display (debugging only) **************/
1196 void method_display(methodinfo *m)
1199 printflags(m->flags);
1201 utf_display(m->name);
1203 utf_display(m->descriptor);
1208 /******************** Function: method_canoverwrite ****************************
1210 Check if m and old are identical with respect to type and name. This means
1211 that old can be overwritten with m.
1213 *******************************************************************************/
1215 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1217 if (m->name != old->name) return false;
1218 if (m->descriptor != old->descriptor) return false;
1219 if (m->flags & ACC_STATIC) return false;
1226 /******************************************************************************/
1227 /************************ Functions for class *********************************/
1228 /******************************************************************************/
1231 /******************** function:: class_getconstant ******************************
1233 retrieves the value at position 'pos' of the constantpool of a class
1234 if the type of the value is other than 'ctype' the system is stopped
1236 *******************************************************************************/
1238 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1240 /* invalid position in constantpool */
1241 /* (pos == 0 is caught by type comparison) */
1242 if (pos >= c->cpcount)
1243 panic("Attempt to access constant outside range");
1245 /* check type of constantpool entry */
1247 if (c->cptags[pos] != ctype) {
1248 class_showconstantpool(c);
1249 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1250 (int) ctype, (int) c->cptags[pos]);
1253 return c->cpinfos[pos];
1257 /********************* Function: class_constanttype ****************************
1259 Determines the type of a class entry in the ConstantPool
1261 *******************************************************************************/
1263 u4 class_constanttype(classinfo *c, u4 pos)
1265 if (pos >= c->cpcount)
1266 panic("Attempt to access constant outside range");
1268 return c->cptags[pos];
1272 /******************** function: class_loadcpool ********************************
1274 loads the constantpool of a class,
1275 the entries are transformed into a simpler format
1276 by resolving references
1277 (a detailed overview of the compact structures can be found in global.h)
1279 *******************************************************************************/
1281 static void class_loadcpool(classinfo *c)
1284 /* The following structures are used to save information which cannot be
1285 processed during the first pass. After the complete constantpool has
1286 been traversed the references can be resolved.
1287 (only in specific order) */
1289 /* CONSTANT_Class_info entries */
1290 typedef struct forward_class {
1291 struct forward_class *next;
1296 /* CONSTANT_String */
1297 typedef struct forward_string {
1298 struct forward_string *next;
1303 /* CONSTANT_NameAndType */
1304 typedef struct forward_nameandtype {
1305 struct forward_nameandtype *next;
1309 } forward_nameandtype;
1311 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1312 typedef struct forward_fieldmethint {
1313 struct forward_fieldmethint *next;
1317 u2 nameandtype_index;
1318 } forward_fieldmethint;
1322 long int dumpsize = dump_size ();
1324 forward_class *forward_classes = NULL;
1325 forward_string *forward_strings = NULL;
1326 forward_nameandtype *forward_nameandtypes = NULL;
1327 forward_fieldmethint *forward_fieldmethints = NULL;
1329 /* number of entries in the constant_pool table plus one */
1330 u4 cpcount = c -> cpcount = suck_u2();
1331 /* allocate memory */
1332 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1333 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1336 panic("Invalid constant_pool_count (0)");
1339 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1342 /* initialize constantpool */
1343 for (idx=0; idx<cpcount; idx++) {
1344 cptags[idx] = CONSTANT_UNUSED;
1345 cpinfos[idx] = NULL;
1349 /******* first pass *******/
1350 /* entries which cannot be resolved now are written into
1351 temporary structures and traversed again later */
1354 while (idx < cpcount) {
1355 /* get constant type */
1359 case CONSTANT_Class: {
1360 forward_class *nfc = DNEW(forward_class);
1362 nfc -> next = forward_classes;
1363 forward_classes = nfc;
1365 nfc -> thisindex = idx;
1366 /* reference to CONSTANT_NameAndType */
1367 nfc -> name_index = suck_u2 ();
1373 case CONSTANT_Fieldref:
1374 case CONSTANT_Methodref:
1375 case CONSTANT_InterfaceMethodref: {
1376 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1378 nff -> next = forward_fieldmethints;
1379 forward_fieldmethints = nff;
1381 nff -> thisindex = idx;
1384 /* class or interface type that contains the declaration of the field or method */
1385 nff -> class_index = suck_u2 ();
1386 /* name and descriptor of the field or method */
1387 nff -> nameandtype_index = suck_u2 ();
1393 case CONSTANT_String: {
1394 forward_string *nfs = DNEW (forward_string);
1396 nfs -> next = forward_strings;
1397 forward_strings = nfs;
1399 nfs -> thisindex = idx;
1400 /* reference to CONSTANT_Utf8_info with string characters */
1401 nfs -> string_index = suck_u2 ();
1407 case CONSTANT_NameAndType: {
1408 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1410 nfn -> next = forward_nameandtypes;
1411 forward_nameandtypes = nfn;
1413 nfn -> thisindex = idx;
1414 /* reference to CONSTANT_Utf8_info containing simple name */
1415 nfn -> name_index = suck_u2 ();
1416 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1417 nfn -> sig_index = suck_u2 ();
1423 case CONSTANT_Integer: {
1424 constant_integer *ci = NEW (constant_integer);
1427 count_const_pool_len += sizeof(constant_integer);
1430 ci -> value = suck_s4 ();
1431 cptags [idx] = CONSTANT_Integer;
1438 case CONSTANT_Float: {
1439 constant_float *cf = NEW (constant_float);
1442 count_const_pool_len += sizeof(constant_float);
1445 cf -> value = suck_float ();
1446 cptags [idx] = CONSTANT_Float;
1452 case CONSTANT_Long: {
1453 constant_long *cl = NEW(constant_long);
1456 count_const_pool_len += sizeof(constant_long);
1459 cl -> value = suck_s8 ();
1460 cptags [idx] = CONSTANT_Long;
1464 panic("Long constant exceeds constant pool");
1468 case CONSTANT_Double: {
1469 constant_double *cd = NEW(constant_double);
1472 count_const_pool_len += sizeof(constant_double);
1475 cd -> value = suck_double ();
1476 cptags [idx] = CONSTANT_Double;
1480 panic("Double constant exceeds constant pool");
1484 case CONSTANT_Utf8: {
1486 /* number of bytes in the bytes array (not string-length) */
1487 u4 length = suck_u2();
1488 cptags [idx] = CONSTANT_Utf8;
1489 /* validate the string */
1490 ASSERT_LEFT(length);
1492 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1494 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1495 panic("Invalid UTF-8 string");
1497 /* insert utf-string into the utf-symboltable */
1498 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1499 /* skip bytes of the string */
1500 skip_nbytes(length);
1506 error ("Unkown constant type: %d",(int) t);
1514 /* resolve entries in temporary structures */
1516 while (forward_classes) {
1518 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1520 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1521 /* retrieve class from class-table */
1522 cpinfos [forward_classes -> thisindex] = class_new (name);
1524 forward_classes = forward_classes -> next;
1528 while (forward_strings) {
1530 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1532 log_text("forward_string:");
1533 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1535 log_text("\n------------------"); */
1536 /* resolve utf-string */
1537 cptags [forward_strings -> thisindex] = CONSTANT_String;
1538 cpinfos [forward_strings -> thisindex] = text;
1540 forward_strings = forward_strings -> next;
1543 while (forward_nameandtypes) {
1544 constant_nameandtype *cn = NEW (constant_nameandtype);
1547 count_const_pool_len += sizeof(constant_nameandtype);
1550 /* resolve simple name and descriptor */
1551 cn -> name = class_getconstant
1552 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1553 cn -> descriptor = class_getconstant
1554 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1556 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1557 cpinfos [forward_nameandtypes -> thisindex] = cn;
1559 forward_nameandtypes = forward_nameandtypes -> next;
1563 while (forward_fieldmethints) {
1564 constant_nameandtype *nat;
1565 constant_FMIref *fmi = NEW (constant_FMIref);
1568 count_const_pool_len += sizeof(constant_FMIref);
1570 /* resolve simple name and descriptor */
1571 nat = class_getconstant
1572 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1575 log_text("trying to resolve:");
1576 log_text(nat->name->text);
1577 switch(forward_fieldmethints ->tag) {
1578 case CONSTANT_Fieldref:
1579 log_text("CONSTANT_Fieldref");
1581 case CONSTANT_InterfaceMethodref:
1582 log_text("CONSTANT_InterfaceMethodref");
1584 case CONSTANT_Methodref:
1585 log_text("CONSTANT_Methodref");
1589 fmi -> class = class_getconstant
1590 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1591 fmi -> name = nat -> name;
1592 fmi -> descriptor = nat -> descriptor;
1594 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1595 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1597 switch (forward_fieldmethints -> tag) {
1598 case CONSTANT_Fieldref: /* check validity of descriptor */
1599 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1601 case CONSTANT_InterfaceMethodref:
1602 case CONSTANT_Methodref: /* check validity of descriptor */
1603 /* XXX check special names (<init>) */
1604 checkmethoddescriptor (fmi->descriptor);
1608 forward_fieldmethints = forward_fieldmethints -> next;
1612 /* class_showconstantpool(c); */
1614 dump_release (dumpsize);
1618 /********************** Function: class_load ***********************************
1620 Loads everything interesting about a class from the class file. The
1621 'classinfo' structure must have been allocated previously.
1623 The super class and the interfaces implemented by this class need not be
1624 loaded. The link is set later by the function 'class_link'.
1626 The loaded class is removed from the list 'unloadedclasses' and added to
1627 the list 'unlinkedclasses'.
1629 *******************************************************************************/
1631 static int class_load(classinfo *c)
1637 count_class_loads++;
1640 /* output for debugging purposes */
1642 char logtext[MAXLOGTEXT];
1643 sprintf(logtext, "Loading class: ");
1644 utf_sprint(logtext + strlen(logtext), c->name);
1648 /* load classdata, throw exception on error */
1650 if (!suck_start(c->name)) {
1651 throw_noclassdeffounderror_message(c->name);
1655 /* check signature */
1656 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1660 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1661 error("File version %d.%d is not supported", (int) ma, (int) mi);
1666 c->erroneous_state = 0;
1667 c->initializing_thread = 0;
1669 c->classUsed = NOTUSED; /* not used initially CO-RT */
1673 c->flags = suck_u2();
1674 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1676 /* check ACC flags consistency */
1677 if ((c->flags & ACC_INTERFACE) != 0) {
1678 if ((c->flags & ACC_ABSTRACT) == 0) {
1679 /* XXX We work around this because interfaces in JDK 1.1 are
1680 * not declared abstract. */
1682 c->flags |= ACC_ABSTRACT;
1683 /* panic("Interface class not declared abstract"); */
1685 if ((c->flags & (ACC_FINAL | ACC_SUPER)) != 0)
1686 panic("Interface class has invalid flags");
1688 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1689 panic("Class is declared both abstract and final");
1693 if (class_getconstant(c, i, CONSTANT_Class) != c)
1694 panic("Invalid this_class in class file");
1696 /* retrieve superclass */
1697 if ((i = suck_u2())) {
1698 c->super = class_getconstant(c, i, CONSTANT_Class);
1700 /* java.lang.Object may not have a super class. */
1701 if (c->name == utf_java_lang_Object)
1702 panic("java.lang.Object with super class");
1704 /* Interfaces must have j.l.O as super class. */
1705 if ((c->flags & ACC_INTERFACE) != 0
1706 && c->super->name != utf_java_lang_Object)
1708 panic("Interface with super class other than java.lang.Object");
1713 /* This is only allowed for java.lang.Object. */
1714 if (c->name != utf_java_lang_Object)
1715 panic("Class (not java.lang.Object) without super class");
1718 /* retrieve interfaces */
1719 c->interfacescount = suck_u2();
1720 c->interfaces = MNEW(classinfo*, c->interfacescount);
1721 for (i = 0; i < c->interfacescount; i++) {
1723 class_getconstant(c, suck_u2(), CONSTANT_Class);
1727 c->fieldscount = suck_u2();
1728 /* utf_display(c->name);
1729 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1731 c->fields = GCNEW(fieldinfo, c->fieldscount);
1732 for (i = 0; i < c->fieldscount; i++) {
1733 field_load(&(c->fields[i]), c);
1737 c->methodscount = suck_u2();
1738 c->methods = MNEW(methodinfo, c->methodscount);
1739 for (i = 0; i < c->methodscount; i++) {
1740 method_load(&(c->methods[i]), c);
1744 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1745 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1746 count_class_infos += sizeof(methodinfo) * c->methodscount;
1749 /* load variable-length attribute structures */
1750 attribute_load(suck_u2(), c);
1755 /* remove class from list of unloaded classes and
1756 add to list of unlinked classes */
1757 list_remove(&unloadedclasses, c);
1758 list_addlast(&unlinkedclasses, c);
1767 /************** internal Function: class_highestinterface ***********************
1769 Used by the function class_link to determine the amount of memory needed
1770 for the interface table.
1772 *******************************************************************************/
1774 static s4 class_highestinterface(classinfo *c)
1779 if (!(c->flags & ACC_INTERFACE)) {
1780 char logtext[MAXLOGTEXT];
1781 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1782 utf_sprint(logtext + strlen(logtext), c->name);
1783 error("%s",logtext);
1787 for (i = 0; i < c->interfacescount; i++) {
1788 s4 h2 = class_highestinterface(c->interfaces[i]);
1796 /* class_addinterface **********************************************************
1798 Is needed by class_link for adding a VTBL to a class. All interfaces
1799 implemented by ic are added as well.
1801 *******************************************************************************/
1803 static void class_addinterface (classinfo *c, classinfo *ic)
1807 vftbl *vftbl = c->vftbl;
1809 if (i >= vftbl->interfacetablelength)
1810 panic ("Inernal error: interfacetable overflow");
1811 if (vftbl->interfacetable[-i])
1814 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1815 vftbl->interfacevftbllength[i] = 1;
1816 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1817 vftbl->interfacetable[-i][0] = NULL;
1820 vftbl->interfacevftbllength[i] = ic->methodscount;
1821 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1824 count_vftbl_len += sizeof(methodptr) *
1825 (ic->methodscount + (ic->methodscount == 0));
1828 for (j=0; j<ic->methodscount; j++) {
1831 for (m = 0; m < sc->methodscount; m++) {
1832 methodinfo *mi = &(sc->methods[m]);
1833 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1834 vftbl->interfacetable[-i][j] =
1835 vftbl->table[mi->vftblindex];
1845 for (j = 0; j < ic->interfacescount; j++)
1846 class_addinterface(c, ic->interfaces[j]);
1850 /******************* Function: class_new_array *********************************
1852 This function is called by class_new to setup an array class.
1854 *******************************************************************************/
1856 void class_new_array(classinfo *c)
1858 classinfo *comp = NULL;
1862 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1864 /* Array classes are not loaded from classfiles. */
1865 list_remove(&unloadedclasses, c);
1867 /* Check array class name */
1868 namelen = c->name->blength;
1869 if (namelen < 2 || c->name->text[0] != '[')
1870 panic("Invalid array class name");
1872 /* Check the component type */
1873 switch (c->name->text[1]) {
1875 /* c is an array of arrays. We have to create the component class. */
1876 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1880 /* c is an array of objects. */
1881 if (namelen < 4 || c->name->text[namelen - 1] != ';')
1882 panic("Invalid array class name");
1883 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1887 /* Setup the array class */
1888 c->super = class_java_lang_Object;
1889 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1891 c->interfacescount = 2;
1892 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1893 c->interfaces[0] = class_java_lang_Cloneable;
1894 c->interfaces[1] = class_java_io_Serializable;
1896 c->methodscount = 1;
1897 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1900 memset(clone, 0, sizeof(methodinfo));
1901 clone->flags = ACC_PUBLIC; /* XXX protected? */
1902 clone->name = utf_new_char("clone");
1903 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1905 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
1906 clone->monoPoly = MONO; /* XXX should be poly? */
1908 /* XXX: field: length? */
1910 /* The array class has to be linked */
1911 list_addlast(&unlinkedclasses,c);
1914 * Array classes which are created after the other classes have been
1915 * loaded and linked are linked explicitely.
1920 loader_load(c->name); /* XXX handle errors */
1924 /****************** Function: class_link_array *********************************
1926 This function is called by class_link to create the
1927 arraydescriptor for an array class.
1929 This function returns NULL if the array cannot be linked because
1930 the component type has not been linked yet.
1932 *******************************************************************************/
1934 static arraydescriptor *class_link_array(classinfo *c)
1936 classinfo *comp = NULL;
1937 int namelen = c->name->blength;
1938 arraydescriptor *desc;
1941 /* Check the component type */
1942 switch (c->name->text[1]) {
1944 /* c is an array of arrays. */
1945 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1946 if (!comp) panic("Could not find component array class.");
1950 /* c is an array of objects. */
1951 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1952 if (!comp) panic("Could not find component class.");
1956 /* If the component type has not been linked return NULL */
1957 if (comp && !comp->linked)
1960 /* Allocate the arraydescriptor */
1961 desc = NEW(arraydescriptor);
1964 /* c is an array of references */
1965 desc->arraytype = ARRAYTYPE_OBJECT;
1966 desc->componentsize = sizeof(void*);
1967 desc->dataoffset = OFFSET(java_objectarray,data);
1969 compvftbl = comp->vftbl;
1971 panic("Component class has no vftbl");
1972 desc->componentvftbl = compvftbl;
1974 if (compvftbl->arraydesc) {
1975 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1976 if (compvftbl->arraydesc->dimension >= 255)
1977 panic("Creating array of dimension >255");
1978 desc->dimension = compvftbl->arraydesc->dimension + 1;
1979 desc->elementtype = compvftbl->arraydesc->elementtype;
1982 desc->elementvftbl = compvftbl;
1983 desc->dimension = 1;
1984 desc->elementtype = ARRAYTYPE_OBJECT;
1988 /* c is an array of a primitive type */
1989 switch (c->name->text[1]) {
1990 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1991 desc->dataoffset = OFFSET(java_booleanarray,data);
1992 desc->componentsize = sizeof(u1);
1995 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1996 desc->dataoffset = OFFSET(java_bytearray,data);
1997 desc->componentsize = sizeof(u1);
2000 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2001 desc->dataoffset = OFFSET(java_chararray,data);
2002 desc->componentsize = sizeof(u2);
2005 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2006 desc->dataoffset = OFFSET(java_doublearray,data);
2007 desc->componentsize = sizeof(double);
2010 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2011 desc->dataoffset = OFFSET(java_floatarray,data);
2012 desc->componentsize = sizeof(float);
2015 case 'I': desc->arraytype = ARRAYTYPE_INT;
2016 desc->dataoffset = OFFSET(java_intarray,data);
2017 desc->componentsize = sizeof(s4);
2020 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2021 desc->dataoffset = OFFSET(java_longarray,data);
2022 desc->componentsize = sizeof(s8);
2025 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2026 desc->dataoffset = OFFSET(java_shortarray,data);
2027 desc->componentsize = sizeof(s2);
2031 panic("Invalid array class name");
2034 desc->componentvftbl = NULL;
2035 desc->elementvftbl = NULL;
2036 desc->dimension = 1;
2037 desc->elementtype = desc->arraytype;
2044 /********************** Function: class_link ***********************************
2046 Tries to link a class. The super class and every implemented interface must
2047 already have been linked. The function calculates the length in bytes that
2048 an instance of this class requires as well as the VTBL for methods and
2051 If the class can be linked, it is removed from the list 'unlinkedclasses'
2052 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2055 Attention: If cyclical class definitions are encountered, the program gets
2056 into an infinite loop (we'll have to work that out)
2058 *******************************************************************************/
2060 void class_link(classinfo *c)
2062 s4 supervftbllength; /* vftbllegnth of super class */
2063 s4 vftbllength; /* vftbllength of current class */
2064 s4 interfacetablelength; /* interface table length */
2065 classinfo *super = c->super; /* super class */
2066 classinfo *ic, *c2; /* intermediate class variables */
2067 vftbl *v; /* vftbl of current class */
2068 s4 i; /* interface/method/field counter */
2069 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2072 /* check if all superclasses are already linked, if not put c at end of
2073 unlinked list and return. Additionally initialize class fields. */
2075 /* check interfaces */
2077 for (i = 0; i < c->interfacescount; i++) {
2078 ic = c->interfaces[i];
2080 list_remove(&unlinkedclasses, c);
2081 list_addlast(&unlinkedclasses, c);
2084 if ((ic->flags & ACC_INTERFACE) == 0) {
2085 dolog("Specified interface is not declared as interface:");
2089 panic("Specified interface is not declared as interface");
2093 /* check super class */
2095 if (super == NULL) { /* class java.long.Object */
2097 c->classUsed = USED; /* Object class is always used CO-RT*/
2099 c->instancesize = sizeof(java_objectheader);
2101 vftbllength = supervftbllength = 0;
2103 c->finalizer = NULL;
2106 if (!super->linked) {
2107 list_remove(&unlinkedclasses, c);
2108 list_addlast(&unlinkedclasses, c);
2112 if ((super->flags & ACC_INTERFACE) != 0)
2113 panic("Interface specified as super class");
2115 /* handle array classes */
2116 /* The component class must have been linked already. */
2117 if (c->name->text[0] == '[')
2118 if ((arraydesc = class_link_array(c)) == NULL) {
2119 list_remove(&unlinkedclasses, c);
2120 list_addlast(&unlinkedclasses, c);
2124 /* Don't allow extending final classes */
2125 if ((super->flags & ACC_FINAL) != 0)
2126 panic("Trying to extend final class");
2128 if (c->flags & ACC_INTERFACE)
2129 c->index = interfaceindex++;
2131 c->index = super->index + 1;
2133 c->instancesize = super->instancesize;
2135 vftbllength = supervftbllength = super->vftbl->vftbllength;
2137 c->finalizer = super->finalizer;
2142 char logtext[MAXLOGTEXT];
2143 sprintf(logtext, "Linking Class: ");
2144 utf_sprint(logtext + strlen(logtext), c->name );
2148 /* compute vftbl length */
2150 for (i = 0; i < c->methodscount; i++) {
2151 methodinfo *m = &(c->methods[i]);
2153 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2154 classinfo *sc = super;
2157 for (j = 0; j < sc->methodscount; j++) {
2158 if (method_canoverwrite(m, &(sc->methods[j]))) {
2159 if ((sc->methods[j].flags & ACC_FINAL) != 0)
2160 panic("Trying to overwrite final method");
2161 m->vftblindex = sc->methods[j].vftblindex;
2162 goto foundvftblindex;
2167 m->vftblindex = (vftbllength++);
2173 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2176 /* compute interfacetable length */
2178 interfacetablelength = 0;
2181 for (i = 0; i < c2->interfacescount; i++) {
2182 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2183 if (h > interfacetablelength)
2184 interfacetablelength = h;
2189 /* allocate virtual function table */
2191 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2192 (vftbllength - 1) + sizeof(methodptr*) *
2193 (interfacetablelength - (interfacetablelength > 0)));
2194 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2195 (interfacetablelength > 1));
2196 c->header.vftbl = c->vftbl = v;
2198 v->vftbllength = vftbllength;
2199 v->interfacetablelength = interfacetablelength;
2200 v->arraydesc = arraydesc;
2202 /* store interface index in vftbl */
2203 if (c->flags & ACC_INTERFACE)
2204 v->baseval = -(c->index);
2206 /* copy virtual function table of super class */
2208 for (i = 0; i < supervftbllength; i++)
2209 v->table[i] = super->vftbl->table[i];
2211 /* add method stubs into virtual function table */
2213 for (i = 0; i < c->methodscount; i++) {
2214 methodinfo *m = &(c->methods[i]);
2215 if (!(m->flags & ACC_STATIC)) {
2216 v->table[m->vftblindex] = m->stubroutine;
2220 /* compute instance size and offset of each field */
2222 for (i = 0; i < c->fieldscount; i++) {
2224 fieldinfo *f = &(c->fields[i]);
2226 if (!(f->flags & ACC_STATIC) ) {
2227 dsize = desc_typesize(f->descriptor);
2228 c->instancesize = ALIGN(c->instancesize, dsize);
2229 f->offset = c->instancesize;
2230 c->instancesize += dsize;
2234 /* initialize interfacetable and interfacevftbllength */
2236 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2239 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2242 for (i = 0; i < interfacetablelength; i++) {
2243 v->interfacevftbllength[i] = 0;
2244 v->interfacetable[-i] = NULL;
2247 /* add interfaces */
2249 for (c2 = c; c2 != NULL; c2 = c2->super)
2250 for (i = 0; i < c2->interfacescount; i++) {
2251 class_addinterface(c, c2->interfaces[i]);
2254 /* add finalizer method (not for java.lang.Object) */
2256 if (super != NULL) {
2258 static utf *finame = NULL;
2259 static utf *fidesc = NULL;
2262 finame = utf_finalize;
2264 fidesc = utf_fidesc;
2266 fi = class_findmethod(c, finame, fidesc);
2268 if (!(fi->flags & ACC_STATIC)) {
2278 list_remove(&unlinkedclasses, c);
2279 list_addlast(&linkedclasses, c);
2283 /******************* Function: class_freepool **********************************
2285 Frees all resources used by this classes Constant Pool.
2287 *******************************************************************************/
2289 static void class_freecpool (classinfo *c)
2295 for (idx=0; idx < c->cpcount; idx++) {
2296 tag = c->cptags[idx];
2297 info = c->cpinfos[idx];
2301 case CONSTANT_Fieldref:
2302 case CONSTANT_Methodref:
2303 case CONSTANT_InterfaceMethodref:
2304 FREE (info, constant_FMIref);
2306 case CONSTANT_Integer:
2307 FREE (info, constant_integer);
2309 case CONSTANT_Float:
2310 FREE (info, constant_float);
2313 FREE (info, constant_long);
2315 case CONSTANT_Double:
2316 FREE (info, constant_double);
2318 case CONSTANT_NameAndType:
2319 FREE (info, constant_nameandtype);
2325 MFREE (c -> cptags, u1, c -> cpcount);
2326 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2330 /*********************** Function: class_free **********************************
2332 Frees all resources used by the class.
2334 *******************************************************************************/
2336 static void class_free(classinfo *c)
2343 MFREE(c->interfaces, classinfo*, c->interfacescount);
2345 for (i = 0; i < c->fieldscount; i++)
2346 field_free(&(c->fields[i]));
2348 for (i = 0; i < c->methodscount; i++)
2349 method_free(&(c->methods[i]));
2350 MFREE(c->methods, methodinfo, c->methodscount);
2352 if ((v = c->vftbl) != NULL) {
2354 mem_free(v->arraydesc,sizeof(arraydescriptor));
2356 for (i = 0; i < v->interfacetablelength; i++) {
2357 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2359 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2361 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2362 sizeof(methodptr*) * (v->interfacetablelength -
2363 (v->interfacetablelength > 0));
2364 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2365 (v->interfacetablelength > 1));
2369 if (c->innerclasscount)
2370 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2372 /* if (c->classvftbl)
2373 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2379 /************************* Function: class_findfield ***************************
2381 Searches a 'classinfo' structure for a field having the given name and
2384 *******************************************************************************/
2386 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2390 for (i = 0; i < c->fieldscount; i++) {
2391 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2392 return &(c->fields[i]);
2395 panic("Can not find field given in CONSTANT_Fieldref");
2397 /* keep compiler happy */
2402 /************************* Function: class_findmethod **************************
2404 Searches a 'classinfo' structure for a method having the given name and
2405 type and returns the index in the class info structure.
2406 If type is NULL, it is ignored.
2408 *******************************************************************************/
2410 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2413 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2415 int buffer_len, pos;
2417 #ifdef JOWENN_DEBUG1
2420 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2422 buffer = MNEW(char, buffer_len);
2424 strcpy(buffer, "class_findmethod: method:");
2425 utf_sprint(buffer + strlen(buffer), name);
2426 strcpy(buffer + strlen(buffer), ", desc: ");
2427 utf_sprint(buffer + strlen(buffer), desc);
2428 strcpy(buffer + strlen(buffer), ", classname: ");
2429 utf_sprint(buffer + strlen(buffer), c->name);
2433 MFREE(buffer, char, buffer_len);
2435 for (i = 0; i < c->methodscount; i++) {
2436 #ifdef JOWENN_DEBUG2
2438 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2440 buffer = MNEW(char, buffer_len);
2442 strcpy(buffer, "class_findmethod: comparing to method:");
2443 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2444 strcpy(buffer + strlen(buffer), ", desc: ");
2445 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2449 MFREE(buffer, char, buffer_len);
2453 if ((c->methods[i].name == name) && ((desc == NULL) ||
2454 (c->methods[i].descriptor == desc))) {
2459 #ifdef JOWENN_DEBUG2
2460 class_showconstantpool(c);
2461 log_text("class_findmethod: returning NULL");
2468 /************************* Function: class_findmethod **************************
2470 Searches a 'classinfo' structure for a method having the given name and
2472 If type is NULL, it is ignored.
2474 *******************************************************************************/
2476 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2480 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2482 int buffer_len, pos;
2484 #ifdef JOWENN_DEBUG1
2487 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2489 buffer = MNEW(char, buffer_len);
2491 strcpy(buffer, "class_findmethod: method:");
2492 utf_sprint(buffer + strlen(buffer), name);
2493 strcpy(buffer + strlen(buffer), ", desc: ");
2494 utf_sprint(buffer + strlen(buffer), desc);
2495 strcpy(buffer + strlen(buffer), ", classname: ");
2496 utf_sprint(buffer + strlen(buffer), c->name);
2500 MFREE(buffer, char, buffer_len);
2502 for (i = 0; i < c->methodscount; i++) {
2503 #ifdef JOWENN_DEBUG2
2505 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2507 buffer = MNEW(char, buffer_len);
2509 strcpy(buffer, "class_findmethod: comparing to method:");
2510 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2511 strcpy(buffer + strlen(buffer), ", desc: ");
2512 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2516 MFREE(buffer, char, buffer_len);
2519 if ((c->methods[i].name == name) && ((desc == NULL) ||
2520 (c->methods[i].descriptor == desc))) {
2521 return &(c->methods[i]);
2524 #ifdef JOWENN_DEBUG2
2525 class_showconstantpool(c);
2526 log_text("class_findmethod: returning NULL");
2531 s4 idx=class_findmethodIndex(c, name, desc);
2532 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2533 if (idx == -1) return NULL;
2535 return &(c->methods[idx]);
2539 /*********************** Function: class_fetchmethod **************************
2541 like class_findmethod, but aborts with an error if the method is not found
2543 *******************************************************************************/
2545 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2548 mi = class_findmethod(c, name, desc);
2551 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2552 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2553 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2554 panic("Method not found");
2561 /************************* Function: class_findmethod_approx ******************
2563 like class_findmethod but ignores the return value when comparing the
2566 *******************************************************************************/
2568 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2572 for (i = 0; i < c->methodscount; i++) {
2573 if (c->methods[i].name == name) {
2574 utf *meth_descr = c->methods[i].descriptor;
2578 return &(c->methods[i]);
2580 if (desc->blength <= meth_descr->blength) {
2581 /* current position in utf text */
2582 char *desc_utf_ptr = desc->text;
2583 char *meth_utf_ptr = meth_descr->text;
2584 /* points behind utf strings */
2585 char *desc_end = utf_end(desc);
2586 char *meth_end = utf_end(meth_descr);
2589 /* compare argument types */
2590 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2592 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2593 break; /* no match */
2596 return &(c->methods[i]); /* all parameter types equal */
2606 /***************** Function: class_resolvemethod_approx ***********************
2608 Searches a class and every super class for a method (without paying
2609 attention to the return value)
2611 *******************************************************************************/
2613 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2616 /* search for method (ignore returntype) */
2617 methodinfo *m = class_findmethod_approx(c, name, desc);
2620 /* search superclass */
2628 /************************* Function: class_resolvemethod ***********************
2630 Searches a class and every super class for a method.
2632 *******************************************************************************/
2634 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2637 methodinfo *m = class_findmethod(c, name, desc);
2639 /* search superclass */
2647 /************************* Function: class_issubclass **************************
2649 Checks if sub is a descendant of super.
2651 *******************************************************************************/
2653 bool class_issubclass(classinfo *sub, classinfo *super)
2656 if (!sub) return false;
2657 if (sub == super) return true;
2663 /****************** Initialization function for classes ******************
2665 In Java, every class can have a static initialization function. This
2666 function has to be called BEFORE calling other methods or accessing static
2669 *******************************************************************************/
2671 void class_init(classinfo *c)
2679 if (!makeinitializations)
2684 c->initialized = true;
2687 count_class_inits++;
2690 /* initialize super class */
2693 char logtext[MAXLOGTEXT];
2694 sprintf(logtext, "Initialize super class ");
2695 utf_sprint(logtext + strlen(logtext), c->super->name);
2696 sprintf(logtext + strlen(logtext), " from ");
2697 utf_sprint(logtext + strlen(logtext), c->name);
2700 class_init(c->super);
2703 /* initialize interface classes */
2704 for (i = 0; i < c->interfacescount; i++) {
2706 char logtext[MAXLOGTEXT];
2707 sprintf(logtext, "Initialize interface class ");
2708 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2709 sprintf(logtext + strlen(logtext), " from ");
2710 utf_sprint(logtext + strlen(logtext), c->name);
2713 class_init(c->interfaces[i]); /* real */
2716 m = class_findmethod(c, utf_clinit, utf_fidesc);
2719 char logtext[MAXLOGTEXT];
2720 sprintf(logtext, "Class ");
2721 utf_sprint(logtext + strlen(logtext), c->name);
2722 sprintf(logtext + strlen(logtext), " has no initializer");
2725 /* goto callinitialize;*/
2729 if (!(m->flags & ACC_STATIC))
2730 panic("Class initializer is not static!");
2733 char logtext[MAXLOGTEXT];
2734 sprintf(logtext, "Starting initializer for class: ");
2735 utf_sprint(logtext + strlen(logtext), c->name);
2744 /* now call the initializer */
2745 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2748 assert(blockInts == 0);
2752 /* we have to throw an exception */
2753 if (*exceptionptr) {
2754 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2755 printf("Caused by: ");
2756 utf_display((*exceptionptr)->vftbl->class->name);
2763 char logtext[MAXLOGTEXT];
2764 sprintf(logtext, "Finished initializer for class: ");
2765 utf_sprint(logtext + strlen(logtext), c->name);
2769 if (c->name == utf_systemclass) {
2770 /* class java.lang.System requires explicit initialization */
2773 printf("#### Initializing class System");
2775 /* find initializing method */
2776 m = class_findmethod(c,
2777 utf_initsystemclass,
2781 /* no method found */
2782 /* printf("initializeSystemClass failed"); */
2791 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2794 assert(blockInts == 0);
2798 if (*exceptionptr) {
2799 printf("#### initializeSystemClass has thrown: ");
2800 utf_display((*exceptionptr)->vftbl->class->name);
2808 /********* Function: find_class_method_constant *********/
2810 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2815 for (i=0; i<c->cpcount; i++) {
2817 e = c -> cpinfos [i];
2820 switch (c -> cptags [i]) {
2821 case CONSTANT_Methodref:
2823 constant_FMIref *fmi = e;
2824 if ( (fmi->class->name == c1)
2825 && (fmi->name == m1)
2826 && (fmi->descriptor == d1)) {
2833 case CONSTANT_InterfaceMethodref:
2835 constant_FMIref *fmi = e;
2836 if ( (fmi->class->name == c1)
2837 && (fmi->name == m1)
2838 && (fmi->descriptor == d1)) {
2852 void class_showconstanti(classinfo *c, int ii)
2858 printf ("#%d: ", (int) i);
2860 switch (c->cptags [i]) {
2861 case CONSTANT_Class:
2862 printf("Classreference -> ");
2863 utf_display(((classinfo*)e)->name);
2866 case CONSTANT_Fieldref:
2867 printf("Fieldref -> "); goto displayFMIi;
2868 case CONSTANT_Methodref:
2869 printf("Methodref -> "); goto displayFMIi;
2870 case CONSTANT_InterfaceMethodref:
2871 printf("InterfaceMethod -> "); goto displayFMIi;
2874 constant_FMIref *fmi = e;
2875 utf_display(fmi->class->name);
2877 utf_display(fmi->name);
2879 utf_display(fmi->descriptor);
2883 case CONSTANT_String:
2884 printf("String -> ");
2887 case CONSTANT_Integer:
2888 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2890 case CONSTANT_Float:
2891 printf("Float -> %f", ((constant_float*)e)->value);
2893 case CONSTANT_Double:
2894 printf("Double -> %f", ((constant_double*)e)->value);
2898 u8 v = ((constant_long*)e)->value;
2900 printf("Long -> %ld", (long int) v);
2902 printf("Long -> HI: %ld, LO: %ld\n",
2903 (long int) v.high, (long int) v.low);
2907 case CONSTANT_NameAndType:
2909 constant_nameandtype *cnt = e;
2910 printf("NameAndType: ");
2911 utf_display(cnt->name);
2913 utf_display(cnt->descriptor);
2921 panic("Invalid type of ConstantPool-Entry");
2928 void class_showconstantpool (classinfo *c)
2933 printf ("---- dump of constant pool ----\n");
2935 for (i=0; i<c->cpcount; i++) {
2936 printf ("#%d: ", (int) i);
2938 e = c -> cpinfos [i];
2941 switch (c -> cptags [i]) {
2942 case CONSTANT_Class:
2943 printf ("Classreference -> ");
2944 utf_display ( ((classinfo*)e) -> name );
2947 case CONSTANT_Fieldref:
2948 printf ("Fieldref -> "); goto displayFMI;
2949 case CONSTANT_Methodref:
2950 printf ("Methodref -> "); goto displayFMI;
2951 case CONSTANT_InterfaceMethodref:
2952 printf ("InterfaceMethod -> "); goto displayFMI;
2955 constant_FMIref *fmi = e;
2956 utf_display ( fmi->class->name );
2958 utf_display ( fmi->name);
2960 utf_display ( fmi->descriptor );
2964 case CONSTANT_String:
2965 printf ("String -> ");
2968 case CONSTANT_Integer:
2969 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2971 case CONSTANT_Float:
2972 printf ("Float -> %f", ((constant_float*)e) -> value);
2974 case CONSTANT_Double:
2975 printf ("Double -> %f", ((constant_double*)e) -> value);
2979 u8 v = ((constant_long*)e) -> value;
2981 printf ("Long -> %ld", (long int) v);
2983 printf ("Long -> HI: %ld, LO: %ld\n",
2984 (long int) v.high, (long int) v.low);
2988 case CONSTANT_NameAndType:
2990 constant_nameandtype *cnt = e;
2991 printf ("NameAndType: ");
2992 utf_display (cnt->name);
2994 utf_display (cnt->descriptor);
2998 printf ("Utf8 -> ");
3002 panic ("Invalid type of ConstantPool-Entry");
3012 /********** Function: class_showmethods (debugging only) *************/
3014 void class_showmethods (classinfo *c)
3018 printf ("--------- Fields and Methods ----------------\n");
3019 printf ("Flags: "); printflags (c->flags); printf ("\n");
3021 printf ("This: "); utf_display (c->name); printf ("\n");
3023 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3025 printf ("Index: %d\n", c->index);
3027 printf ("interfaces:\n");
3028 for (i=0; i < c-> interfacescount; i++) {
3030 utf_display (c -> interfaces[i] -> name);
3031 printf (" (%d)\n", c->interfaces[i] -> index);
3034 printf ("fields:\n");
3035 for (i=0; i < c -> fieldscount; i++) {
3036 field_display (&(c -> fields[i]));
3039 printf ("methods:\n");
3040 for (i=0; i < c -> methodscount; i++) {
3041 methodinfo *m = &(c->methods[i]);
3042 if ( !(m->flags & ACC_STATIC))
3043 printf ("vftblindex: %d ", m->vftblindex);
3045 method_display ( m );
3049 printf ("Virtual function table:\n");
3050 for (i=0; i<c->vftbl->vftbllength; i++) {
3051 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3058 /******************************************************************************/
3059 /******************* General functions for the class loader *******************/
3060 /******************************************************************************/
3062 /********************* Function: loader_load ***********************************
3064 Loads and links the class desired class and each class and interface
3066 Returns: a pointer to this class
3068 *******************************************************************************/
3070 static int loader_load_running = 0;
3072 classinfo *loader_load(utf *topname)
3078 classinfo *notlinkable;
3080 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3081 pthread_mutex_lock(&compiler_mutex);
3084 /* avoid recursive calls */
3085 if (loader_load_running)
3086 return class_new(topname);
3088 loader_load_running++;
3093 starttime = getcputime();
3095 top = class_new(topname);
3098 while ((c = list_first(&unloadedclasses))) {
3099 if (!class_load(c)) {
3101 dolog("Failed to load class");
3102 list_remove(&unloadedclasses, c);
3109 dolog("Linking...");
3111 /* XXX added a hack to break infinite linking loops. A better
3112 * linking algorithm would be nice. -Edwin */
3114 while ((c = list_first(&unlinkedclasses))) {
3119 else if (notlinkable == c) {
3120 /* We tried to link this class for the second time and
3121 * no other classes were linked in between, so we are
3125 dolog("Cannot resolve linking dependencies");
3128 throw_linkageerror_message(c->name);
3136 dolog("Linking done.");
3139 loader_compute_subclasses();
3142 if (getloadingtime) {
3143 stoptime = getcputime();
3144 loadingtime += (stoptime - starttime);
3148 loader_load_running--;
3150 /* check if a former loader_load call tried to load/link the class and
3151 failed. This is needed because the class didn't appear in the
3152 undloadclasses or unlinkedclasses list during this class. */
3155 if (linkverbose) dolog("Failed to load class (former call)");
3156 throw_noclassdeffounderror_message(top->name);
3159 } else if (!top->linked) {
3161 dolog("Failed to link class (former call)");
3162 throw_linkageerror_message(top->name);
3169 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3170 pthread_mutex_unlock(&compiler_mutex);
3173 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
3179 /****************** Function: loader_load_sysclass ****************************
3181 Loads and links the class desired class and each class and interface
3184 The pointer to the classinfo is stored in *top if top != NULL.
3185 The pointer is also returned.
3187 If the class could not be loaded the function aborts with an error.
3189 *******************************************************************************/
3191 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3195 if ((cls = loader_load(topname)) == NULL) {
3196 log_plain("Could not load important system class: ");
3197 log_plain_utf(topname);
3199 panic("Could not load important system class");
3202 if (top) *top = cls;
3208 /**************** function: create_primitive_classes ***************************
3210 create classes representing primitive types
3212 ********************************************************************************/
3215 void create_primitive_classes()
3219 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3220 /* create primitive class */
3221 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3222 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3223 c -> impldBy = NULL;
3225 /* prevent loader from loading primitive class */
3226 list_remove (&unloadedclasses, c);
3228 /* add to unlinked classes */
3229 list_addlast (&unlinkedclasses, c);
3230 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3233 primitivetype_table[i].class_primitive = c;
3235 /* create class for wrapping the primitive type */
3236 primitivetype_table[i].class_wrap =
3237 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3238 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3239 primitivetype_table[i].class_wrap -> impldBy = NULL;
3241 /* create the primitive array class */
3242 if (primitivetype_table[i].arrayname) {
3243 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3244 primitivetype_table[i].arrayclass = c;
3246 if (!c->linked) class_link(c);
3247 primitivetype_table[i].arrayvftbl = c->vftbl;
3252 /**************** function: class_primitive_from_sig ***************************
3254 return the primitive class indicated by the given signature character
3256 If the descriptor does not indicate a valid primitive type the
3257 return value is NULL.
3259 ********************************************************************************/
3261 classinfo *class_primitive_from_sig(char sig)
3264 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3265 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3266 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3267 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3268 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3269 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3270 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3271 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3272 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3277 /****************** function: class_from_descriptor ****************************
3279 return the class indicated by the given descriptor
3281 utf_ptr....first character of descriptor
3282 end_ptr....first character after the end of the string
3283 next.......if non-NULL, *next is set to the first character after
3284 the descriptor. (Undefined if an error occurs.)
3286 mode.......a combination (binary or) of the following flags:
3288 (Flags marked with * are the default settings.)
3290 What to do if a reference type descriptor is parsed successfully:
3292 CLASSLOAD_SKIP...skip it and return something != NULL
3293 * CLASSLOAD_NEW....get classinfo * via class_new
3294 CLASSLOAD_LOAD...get classinfo * via loader_load
3296 How to handle primitive types:
3298 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3299 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3301 How to handle "V" descriptors:
3303 * CLASSLOAD_VOID.....handle it like other primitive types
3304 CLASSLOAD_NOVOID...treat it as an error
3306 How to deal with extra characters after the end of the
3309 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3310 CLASSLOAD_CHECKEND.....treat them as an error
3312 How to deal with errors:
3314 * CLASSLOAD_PANIC....abort execution with an error message
3315 CLASSLOAD_NOPANIC..return NULL on error
3317 ********************************************************************************/
3319 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3320 char **next, int mode)
3322 char *start = utf_ptr;
3326 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3328 if (mode & CLASSLOAD_CHECKEND)
3329 error |= (utf_ptr != end_ptr);
3332 if (next) *next = utf_ptr;
3336 if (mode & CLASSLOAD_NOVOID)
3347 return (mode & CLASSLOAD_NULLPRIMITIVE)
3349 : class_primitive_from_sig(*start);
3356 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3357 name = utf_new(start,utf_ptr-start);
3358 return (mode & CLASSLOAD_LOAD)
3359 ? loader_load(name) : class_new(name); /* XXX */
3363 /* An error occurred */
3364 if (mode & CLASSLOAD_NOPANIC)
3367 log_plain("Invalid descriptor at beginning of '");
3368 log_plain_utf(utf_new(start, end_ptr-start));
3372 panic("Invalid descriptor");
3374 /* keep compiler happy */
3379 /******************* function: type_from_descriptor ****************************
3381 return the basic type indicated by the given descriptor
3383 This function parses a descriptor and returns its basic type as
3384 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3386 cls...if non-NULL the referenced variable is set to the classinfo *
3387 returned by class_from_descriptor.
3389 For documentation of the arguments utf_ptr, end_ptr, next and mode
3390 see class_from_descriptor. The only difference is that
3391 type_from_descriptor always uses CLASSLOAD_PANIC.
3393 ********************************************************************************/
3395 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3396 char **next, int mode)
3399 if (!cls) cls = &mycls;
3400 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3417 return TYPE_ADDRESS;
3421 /*************** function: create_pseudo_classes *******************************
3423 create pseudo classes used by the typechecker
3425 ********************************************************************************/
3427 static void create_pseudo_classes()
3429 /* pseudo class for Arraystubs (extends java.lang.Object) */
3431 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3432 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3434 pseudo_class_Arraystub->super = class_java_lang_Object;
3435 pseudo_class_Arraystub->interfacescount = 2;
3436 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3437 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3438 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3440 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3441 class_link(pseudo_class_Arraystub);
3443 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3445 /* pseudo class representing the null type */
3447 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3448 list_remove(&unloadedclasses, pseudo_class_Null);
3450 pseudo_class_Null->super = class_java_lang_Object;
3452 list_addlast(&unlinkedclasses, pseudo_class_Null);
3453 class_link(pseudo_class_Null);
3455 /* pseudo class representing new uninitialized objects */
3457 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3458 list_remove(&unloadedclasses, pseudo_class_New);
3460 pseudo_class_New->super = class_java_lang_Object;
3462 list_addlast(&unlinkedclasses, pseudo_class_New);
3463 class_link(pseudo_class_New);
3467 /********************** Function: loader_init **********************************
3469 Initializes all lists and loads all classes required for the system or the
3472 *******************************************************************************/
3474 void loader_init(u1 *stackbottom)
3478 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3479 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3480 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3482 /* create utf-symbols for pointer comparison of frequently used strings */
3483 utf_innerclasses = utf_new_char("InnerClasses");
3484 utf_constantvalue = utf_new_char("ConstantValue");
3485 utf_code = utf_new_char("Code");
3486 utf_finalize = utf_new_char("finalize");
3487 utf_fidesc = utf_new_char("()V");
3488 utf_init = utf_new_char("<init>");
3489 utf_clinit = utf_new_char("<clinit>");
3490 utf_initsystemclass = utf_new_char("initializeSystemClass");
3491 utf_systemclass = utf_new_char("java/lang/System");
3492 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3493 utf_initialize = utf_new_char("initialize");
3494 utf_initializedesc = utf_new_char("(I)V");
3496 utf_vmclass = utf_new_char("java/lang/VMClass");
3497 utf_java_lang_Object= utf_new_char("java/lang/Object");
3499 /* create some important classes */
3500 /* These classes have to be created now because the classinfo
3501 * pointers are used in the loading code.
3503 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3504 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3505 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3506 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3508 if (verbose) log_text("loader_init: java/lang/Object");
3509 /* load the classes which were created above */
3510 loader_load_sysclass(NULL, class_java_lang_Object->name);
3512 loader_inited = 1; /*JOWENN*/
3514 loader_load_sysclass(&class_java_lang_Throwable,
3515 utf_new_char("java/lang/Throwable"));
3517 if (verbose) log_text("loader_init: loader_load: java/lang/ClassCastException");
3518 loader_load_sysclass(&class_java_lang_ClassCastException,
3519 utf_new_char ("java/lang/ClassCastException"));
3520 loader_load_sysclass(&class_java_lang_NullPointerException,
3521 utf_new_char ("java/lang/NullPointerException"));
3522 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3523 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3524 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3525 utf_new_char ("java/lang/NegativeArraySizeException"));
3526 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3527 utf_new_char ("java/lang/OutOfMemoryError"));
3528 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3529 utf_new_char ("java/lang/ArrayStoreException"));
3530 loader_load_sysclass(&class_java_lang_ArithmeticException,
3531 utf_new_char ("java/lang/ArithmeticException"));
3532 loader_load_sysclass(&class_java_lang_ThreadDeath,
3533 utf_new_char ("java/lang/ThreadDeath"));
3535 /* create classes representing primitive types */
3536 create_primitive_classes();
3538 /* create classes used by the typechecker */
3539 create_pseudo_classes();
3541 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3542 stringtable_update();
3549 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3550 proto_java_lang_ClassCastException =
3551 builtin_new(class_java_lang_ClassCastException);
3553 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3555 proto_java_lang_NullPointerException =
3556 builtin_new(class_java_lang_NullPointerException);
3557 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3559 proto_java_lang_ArrayIndexOutOfBoundsException =
3560 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3562 proto_java_lang_NegativeArraySizeException =
3563 builtin_new(class_java_lang_NegativeArraySizeException);
3565 proto_java_lang_OutOfMemoryError =
3566 builtin_new(class_java_lang_OutOfMemoryError);
3568 proto_java_lang_ArithmeticException =
3569 builtin_new(class_java_lang_ArithmeticException);
3571 proto_java_lang_ArrayStoreException =
3572 builtin_new(class_java_lang_ArrayStoreException);
3574 proto_java_lang_ThreadDeath =
3575 builtin_new(class_java_lang_ThreadDeath);
3581 /********************* Function: loader_initclasses ****************************
3583 Initializes all loaded but uninitialized classes
3585 *******************************************************************************/
3588 /* XXX TWISTI: i think we do not need this */
3589 void loader_initclasses ()
3593 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3594 pthread_mutex_lock(&compiler_mutex);
3597 intsDisable(); /* schani */
3599 if (makeinitializations) {
3600 c = list_first(&linkedclasses);
3603 c = list_next(&linkedclasses, c);
3607 intsRestore(); /* schani */
3609 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3610 pthread_mutex_unlock(&compiler_mutex);
3616 static void loader_compute_class_values(classinfo *c)
3620 c->vftbl->baseval = ++classvalue;
3623 while (subs != NULL) {
3624 loader_compute_class_values(subs);
3625 subs = subs->nextsub;
3627 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3632 for (i = 0; i < c->index; i++)
3634 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3635 utf_display(c->name);
3642 void loader_compute_subclasses()
3646 intsDisable(); /* schani */
3648 c = list_first(&linkedclasses);
3650 if (!(c->flags & ACC_INTERFACE)) {
3654 c = list_next(&linkedclasses, c);
3657 c = list_first(&linkedclasses);
3659 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3660 c->nextsub = c->super->sub;
3663 c = list_next(&linkedclasses, c);
3667 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3670 loader_compute_class_values(class_java_lang_Object);
3671 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3675 intsRestore(); /* schani */
3679 /******************** function classloader_buffer ******************************
3681 sets buffer for reading classdata
3683 *******************************************************************************/
3685 void classload_buffer(u1 *buf, int len)
3688 classbuffer_size = len;
3689 classbuf_pos = buf - 1;
3693 /******************** Function: loader_close ***********************************
3697 *******************************************************************************/
3703 while ((c = list_first(&unloadedclasses))) {
3704 list_remove(&unloadedclasses, c);
3707 while ((c = list_first(&unlinkedclasses))) {
3708 list_remove(&unlinkedclasses, c);
3711 while ((c = list_first(&linkedclasses))) {
3712 list_remove(&linkedclasses, c);
3719 * These are local overrides for various environment variables in Emacs.
3720 * Please do not remove this and leave it at the end of the file, where
3721 * Emacs will automagically detect them.
3722 * ---------------------------------------------------------------------
3725 * indent-tabs-mode: t