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 833 2004-01-04 22:10:24Z jowenn $
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;
109 /* important system classes ***************************************************/
111 classinfo *class_java_lang_Object;
112 classinfo *class_java_lang_String;
114 classinfo *class_java_lang_Throwable;
115 classinfo *class_java_lang_Cloneable;
116 classinfo *class_java_io_Serializable;
118 /* Pseudo classes for the typechecker */
119 classinfo *pseudo_class_Arraystub = NULL;
120 classinfo *pseudo_class_Null = NULL;
121 classinfo *pseudo_class_New = NULL;
122 vftbl *pseudo_class_Arraystub_vftbl = NULL;
125 /* These are made static so they cannot be used for throwing in native */
127 static classinfo *class_java_lang_ClassCastException;
128 static classinfo *class_java_lang_NullPointerException;
129 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
130 static classinfo *class_java_lang_NegativeArraySizeException;
131 static classinfo *class_java_lang_OutOfMemoryError;
132 static classinfo *class_java_lang_ArithmeticException;
133 static classinfo *class_java_lang_ArrayStoreException;
134 static classinfo *class_java_lang_ThreadDeath;
136 static methodinfo method_clone_array;
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) {
449 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
450 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
451 unz_file_info file_info;
452 /*log_text("Class found in zip file");*/
453 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
454 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
455 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
456 classbuffer_size = file_info.uncompressed_size;
457 classbuffer = MNEW(u1, classbuffer_size);
458 classbuf_pos = classbuffer - 1;
459 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
460 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
461 unzCloseCurrentFile(currPos->archive.uf);
464 MFREE(classbuffer, u1, classbuffer_size);
465 log_text("Error while unzipping");
467 } else log_text("Error while opening file in archive");
468 } else log_text("Error while retrieving fileinfo");
470 unzCloseCurrentFile(currPos->archive.uf);
473 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
474 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
475 classfile = fopen(currPos->filepath.filename, "r");
476 if (classfile) { /* file exists */
478 /* determine size of classfile */
480 /* dolog("File: %s",filename); */
482 err = stat(currPos->filepath.filename, &buffer);
484 if (!err) { /* read classfile data */
485 classbuffer_size = buffer.st_size;
486 classbuffer = MNEW(u1, classbuffer_size);
487 classbuf_pos = classbuffer - 1;
488 fread(classbuffer, 1, classbuffer_size, classfile);
497 dolog("Warning: Can not open class file '%s'", filename);
504 /************************** function suck_stop *********************************
506 frees memory for buffer with classfile data.
507 Caution: this function may only be called if buffer has been allocated
508 by suck_start with reading a file
510 *******************************************************************************/
514 /* determine amount of classdata not retrieved by suck-operations */
516 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
518 if (classdata_left > 0) {
520 dolog("There are %d access bytes at end of classfile",
527 MFREE(classbuffer, u1, classbuffer_size);
532 /******************************************************************************/
533 /******************* Some support functions ***********************************/
534 /******************************************************************************/
536 void fprintflags (FILE *fp, u2 f)
538 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
539 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
540 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
541 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
542 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
543 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
544 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
545 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
546 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
547 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
548 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
552 /********** internal function: printflags (only for debugging) ***************/
554 void printflags(u2 f)
556 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
557 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
558 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
559 if ( f & ACC_STATIC ) printf (" STATIC");
560 if ( f & ACC_FINAL ) printf (" FINAL");
561 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
562 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
563 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
564 if ( f & ACC_NATIVE ) printf (" NATIVE");
565 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
566 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
570 /************************* Function: skipattribute *****************************
572 skips a (1) 'attribute' structure in the class file
574 *******************************************************************************/
576 static void skipattribute()
585 /********************** Function: skipattributebody ****************************
587 skips an attribute after the 16 bit reference to attribute_name has already
590 *******************************************************************************/
592 static void skipattributebody()
600 /************************* Function: skipattributes ****************************
602 skips num attribute structures
604 *******************************************************************************/
606 static void skipattributes(u4 num)
609 for (i = 0; i < num; i++)
614 /******************** function: innerclass_getconstant ************************
616 like class_getconstant, but if cptags is ZERO null is returned
618 *******************************************************************************/
620 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
622 /* invalid position in constantpool */
623 if (pos >= c->cpcount)
624 panic("Attempt to access constant outside range");
626 /* constantpool entry of type 0 */
630 /* check type of constantpool entry */
631 if (c->cptags[pos] != ctype) {
632 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
633 (int) ctype, (int) c->cptags[pos] );
636 return c->cpinfos[pos];
640 /************************ function: attribute_load ****************************
642 read attributes from classfile
644 *******************************************************************************/
646 static void attribute_load(u4 num, classinfo *c)
650 for (i = 0; i < num; i++) {
651 /* retrieve attribute name */
652 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
654 if (aname == utf_innerclasses) {
655 /* innerclasses attribute */
657 /* skip attribute length */
659 /* number of records */
660 c->innerclasscount = suck_u2();
661 /* allocate memory for innerclass structure */
662 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
664 for (j = 0; j < c->innerclasscount; j++) {
665 /* The innerclass structure contains a class with an encoded name,
666 its defining scope, its simple name and a bitmask of the access flags.
667 If an inner class is not a member, its outer_class is NULL,
668 if a class is anonymous, its name is NULL. */
670 innerclassinfo *info = c->innerclass + j;
672 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
673 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
674 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
675 info->flags = suck_u2(); /* access_flags bitmask */
679 /* unknown attribute */
686 /******************* function: checkfielddescriptor ****************************
688 checks whether a field-descriptor is valid and aborts otherwise
689 all referenced classes are inserted into the list of unloaded classes
691 *******************************************************************************/
693 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
695 class_from_descriptor(utf_ptr,end_pos,NULL,
697 | CLASSLOAD_NULLPRIMITIVE
699 | CLASSLOAD_CHECKEND);
701 char *tstart; /* pointer to start of classname */
703 char *start = utf_ptr;
705 switch (*utf_ptr++) {
719 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
720 panic ("Ill formed descriptor");
724 panic ("Ill formed descriptor");
727 /* exceeding characters */
728 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
733 /******************* function checkmethoddescriptor ****************************
735 checks whether a method-descriptor is valid and aborts otherwise.
736 All referenced classes are inserted into the list of unloaded classes.
738 *******************************************************************************/
740 static void checkmethoddescriptor (utf *d)
742 char *utf_ptr = d->text; /* current position in utf text */
743 char *end_pos = utf_end(d); /* points behind utf string */
745 /* method descriptor must start with parenthesis */
746 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
748 /* check arguments */
749 while (utf_ptr != end_pos && *utf_ptr != ')') {
750 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
752 | CLASSLOAD_NULLPRIMITIVE
756 if (utf_ptr == end_pos) panic("Missing return type in method descriptor");
757 utf_ptr++; /* skip ')' */
759 class_from_descriptor(utf_ptr,end_pos,NULL,
761 | CLASSLOAD_NULLPRIMITIVE
762 | CLASSLOAD_CHECKEND);
765 /* XXX check length */
766 /* check arguments */
767 while ((c = *utf_ptr++) != ')') {
784 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
785 panic ("Ill formed method descriptor");
789 panic ("Ill formed methodtype-descriptor");
793 /* check returntype */
795 /* returntype void */
796 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
799 /* treat as field-descriptor */
800 checkfielddescriptor (utf_ptr,end_pos);
805 /***************** Function: print_arraydescriptor ****************************
807 Debugging helper for displaying an arraydescriptor
809 *******************************************************************************/
811 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
814 fprintf(file, "<NULL>");
819 if (desc->componentvftbl) {
820 if (desc->componentvftbl->class)
821 utf_fprint(file, desc->componentvftbl->class->name);
823 fprintf(file, "<no classinfo>");
829 if (desc->elementvftbl) {
830 if (desc->elementvftbl->class)
831 utf_fprint(file, desc->elementvftbl->class->name);
833 fprintf(file, "<no classinfo>");
837 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
838 desc->dataoffset, desc->componentsize);
842 /******************************************************************************/
843 /************************** Functions for fields ****************************/
844 /******************************************************************************/
847 /************************ Function: field_load *********************************
849 Load everything about a class field from the class file and fill a
850 'fieldinfo' structure. For static fields, space in the data segment is
853 *******************************************************************************/
855 static void field_load(fieldinfo *f, classinfo *c)
860 f->flags = suck_u2(); /* ACC flags */
861 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
862 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
863 f->type = jtype = desc_to_type(f->descriptor); /* data type */
864 f->offset = 0; /* offset from start of object */
868 /* check flag consistency */
870 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
871 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
872 panic("Field has invalid access flags");
873 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
874 panic("Field is declared final and volatile");
875 if ((c->flags & ACC_INTERFACE) != 0) {
876 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
877 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
878 panic("Interface field is not declared static final public");
883 case TYPE_INT: f->value.i = 0; break;
884 case TYPE_FLOAT: f->value.f = 0.0; break;
885 case TYPE_DOUBLE: f->value.d = 0.0; break;
886 case TYPE_ADDRESS: f->value.a = NULL; break;
889 f->value.l = 0; break;
891 f->value.l.low = 0; f->value.l.high = 0; break;
895 /* read attributes */
897 for (i = 0; i < attrnum; i++) {
901 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
903 if (aname != utf_constantvalue) {
904 /* unknown attribute */
908 /* constant value attribute */
910 /* skip attribute length */
912 /* index of value in constantpool */
915 /* initialize field with value from constantpool */
918 constant_integer *ci =
919 class_getconstant(c, pindex, CONSTANT_Integer);
920 f->value.i = ci->value;
926 class_getconstant(c, pindex, CONSTANT_Long);
927 f->value.l = cl->value;
933 class_getconstant(c, pindex, CONSTANT_Float);
934 f->value.f = cf->value;
939 constant_double *cd =
940 class_getconstant(c, pindex, CONSTANT_Double);
941 f->value.d = cd->value;
946 utf *u = class_getconstant(c, pindex, CONSTANT_String);
947 /* create javastring from compressed utf8-string */
948 f->value.a = literalstring_new(u);
953 log_text ("Invalid Constant - Type");
960 /********************** function: field_free **********************************/
962 static void field_free (fieldinfo *f)
968 /**************** Function: field_display (debugging only) ********************/
970 void field_display(fieldinfo *f)
973 printflags(f->flags);
975 utf_display(f->name);
977 utf_display(f->descriptor);
978 printf(" offset: %ld\n", (long int) (f->offset));
982 /******************************************************************************/
983 /************************* Functions for methods ******************************/
984 /******************************************************************************/
987 /*********************** Function: method_load *********************************
989 Loads a method from the class file and fills an existing 'methodinfo'
990 structure. For native methods, the function pointer field is set to the
991 real function pointer, for JavaVM methods a pointer to the compiler is used
994 *******************************************************************************/
996 static void method_load(methodinfo *m, classinfo *c)
999 static utf* name_init = NULL;
1000 static utf* name_clinit = NULL;
1003 count_all_methods++;
1008 m->flags = suck_u2();
1009 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1010 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1011 checkmethoddescriptor(m->descriptor);
1013 /* check flag consistency */
1016 name_init = utf_new_char("<init>");
1017 name_clinit = utf_new_char("<clinit>");
1019 /* XXX could check if <clinit> is STATIC */
1020 if (m->name != name_clinit) {
1021 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1022 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1023 panic("Method has invalid access flags");
1024 if ((m->flags & ACC_ABSTRACT) != 0) {
1025 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1026 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1027 panic("Abstract method has invalid flags set");
1029 if ((c->flags & ACC_INTERFACE) != 0) {
1030 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1031 != (ACC_ABSTRACT | ACC_PUBLIC))
1032 panic("Interface method is not declared abstract and public");
1034 if (m->name == name_init) {
1035 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1036 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1037 panic("Instance initialization method has invalid flags set");
1043 m->exceptiontable = NULL;
1044 m->entrypoint = NULL;
1046 m->stubroutine = NULL;
1047 m->methodUsed = NOTUSED;
1050 m->subRedefsUsed = 0;
1054 if (!(m->flags & ACC_NATIVE)) {
1055 m->stubroutine = createcompilerstub(m);
1058 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1059 (m->flags & ACC_STATIC) != 0);
1061 m->stubroutine = createnativestub(f, m);
1066 attrnum = suck_u2();
1067 for (i = 0; i < attrnum; i++) {
1070 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1072 if (aname != utf_code) {
1073 skipattributebody();
1078 panic("Two code-attributes for one method!");
1081 m->maxstack = suck_u2();
1082 m->maxlocals = suck_u2();
1083 codelen = suck_u4();
1085 panic("bytecode has zero length");
1086 if (codelen > 65536)
1087 panic("bytecode too long");
1088 m->jcodelength = codelen;
1089 m->jcode = MNEW(u1, m->jcodelength);
1090 suck_nbytes(m->jcode, m->jcodelength);
1091 m->exceptiontablelength = suck_u2();
1093 MNEW(exceptiontable, m->exceptiontablelength);
1096 count_vmcode_len += m->jcodelength + 18;
1097 count_extable_len += 8 * m->exceptiontablelength;
1100 for (e = 0; e < m->exceptiontablelength; e++) {
1102 m->exceptiontable[e].startpc = suck_u2();
1103 m->exceptiontable[e].endpc = suck_u2();
1104 m->exceptiontable[e].handlerpc = suck_u2();
1108 m->exceptiontable[e].catchtype = NULL;
1111 m->exceptiontable[e].catchtype =
1112 class_getconstant(c, idx, CONSTANT_Class);
1116 skipattributes(suck_u2());
1122 /********************* Function: method_free ***********************************
1124 frees all memory that was allocated for this method
1126 *******************************************************************************/
1128 static void method_free(methodinfo *m)
1131 MFREE(m->jcode, u1, m->jcodelength);
1133 if (m->exceptiontable)
1134 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1137 CFREE(m->mcode, m->mcodelength);
1139 if (m->stubroutine) {
1140 if (m->flags & ACC_NATIVE) {
1141 removenativestub(m->stubroutine);
1144 removecompilerstub(m->stubroutine);
1150 /************** Function: method_display (debugging only) **************/
1152 void method_display(methodinfo *m)
1155 printflags(m->flags);
1157 utf_display(m->name);
1159 utf_display(m->descriptor);
1164 /******************** Function: method_canoverwrite ****************************
1166 Check if m and old are identical with respect to type and name. This means
1167 that old can be overwritten with m.
1169 *******************************************************************************/
1171 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1173 if (m->name != old->name) return false;
1174 if (m->descriptor != old->descriptor) return false;
1175 if (m->flags & ACC_STATIC) return false;
1182 /******************************************************************************/
1183 /************************ Functions for class *********************************/
1184 /******************************************************************************/
1187 /******************** function:: class_getconstant ******************************
1189 retrieves the value at position 'pos' of the constantpool of a class
1190 if the type of the value is other than 'ctype' the system is stopped
1192 *******************************************************************************/
1194 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1196 /* invalid position in constantpool */
1197 /* (pos == 0 is caught by type comparison) */
1198 if (pos >= c->cpcount)
1199 panic("Attempt to access constant outside range");
1201 /* check type of constantpool entry */
1203 if (c->cptags[pos] != ctype) {
1204 class_showconstantpool(c);
1205 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1206 (int) ctype, (int) c->cptags[pos]);
1209 return c->cpinfos[pos];
1213 /********************* Function: class_constanttype ****************************
1215 Determines the type of a class entry in the ConstantPool
1217 *******************************************************************************/
1219 u4 class_constanttype(classinfo *c, u4 pos)
1221 if (pos >= c->cpcount)
1222 panic("Attempt to access constant outside range");
1224 return c->cptags[pos];
1228 /******************** function: class_loadcpool ********************************
1230 loads the constantpool of a class,
1231 the entries are transformed into a simpler format
1232 by resolving references
1233 (a detailed overview of the compact structures can be found in global.h)
1235 *******************************************************************************/
1237 static void class_loadcpool(classinfo *c)
1240 /* The following structures are used to save information which cannot be
1241 processed during the first pass. After the complete constantpool has
1242 been traversed the references can be resolved.
1243 (only in specific order) */
1245 /* CONSTANT_Class_info entries */
1246 typedef struct forward_class {
1247 struct forward_class *next;
1252 /* CONSTANT_String */
1253 typedef struct forward_string {
1254 struct forward_string *next;
1259 /* CONSTANT_NameAndType */
1260 typedef struct forward_nameandtype {
1261 struct forward_nameandtype *next;
1265 } forward_nameandtype;
1267 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1268 typedef struct forward_fieldmethint {
1269 struct forward_fieldmethint *next;
1273 u2 nameandtype_index;
1274 } forward_fieldmethint;
1278 long int dumpsize = dump_size ();
1280 forward_class *forward_classes = NULL;
1281 forward_string *forward_strings = NULL;
1282 forward_nameandtype *forward_nameandtypes = NULL;
1283 forward_fieldmethint *forward_fieldmethints = NULL;
1285 /* number of entries in the constant_pool table plus one */
1286 u4 cpcount = c -> cpcount = suck_u2();
1287 /* allocate memory */
1288 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1289 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1292 panic("Invalid constant_pool_count (0)");
1295 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1298 /* initialize constantpool */
1299 for (idx=0; idx<cpcount; idx++) {
1300 cptags[idx] = CONSTANT_UNUSED;
1301 cpinfos[idx] = NULL;
1305 /******* first pass *******/
1306 /* entries which cannot be resolved now are written into
1307 temporary structures and traversed again later */
1310 while (idx < cpcount) {
1311 /* get constant type */
1315 case CONSTANT_Class: {
1316 forward_class *nfc = DNEW(forward_class);
1318 nfc -> next = forward_classes;
1319 forward_classes = nfc;
1321 nfc -> thisindex = idx;
1322 /* reference to CONSTANT_NameAndType */
1323 nfc -> name_index = suck_u2 ();
1329 case CONSTANT_Fieldref:
1330 case CONSTANT_Methodref:
1331 case CONSTANT_InterfaceMethodref: {
1332 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1334 nff -> next = forward_fieldmethints;
1335 forward_fieldmethints = nff;
1337 nff -> thisindex = idx;
1340 /* class or interface type that contains the declaration of the field or method */
1341 nff -> class_index = suck_u2 ();
1342 /* name and descriptor of the field or method */
1343 nff -> nameandtype_index = suck_u2 ();
1349 case CONSTANT_String: {
1350 forward_string *nfs = DNEW (forward_string);
1352 nfs -> next = forward_strings;
1353 forward_strings = nfs;
1355 nfs -> thisindex = idx;
1356 /* reference to CONSTANT_Utf8_info with string characters */
1357 nfs -> string_index = suck_u2 ();
1363 case CONSTANT_NameAndType: {
1364 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1366 nfn -> next = forward_nameandtypes;
1367 forward_nameandtypes = nfn;
1369 nfn -> thisindex = idx;
1370 /* reference to CONSTANT_Utf8_info containing simple name */
1371 nfn -> name_index = suck_u2 ();
1372 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1373 nfn -> sig_index = suck_u2 ();
1379 case CONSTANT_Integer: {
1380 constant_integer *ci = NEW (constant_integer);
1383 count_const_pool_len += sizeof(constant_integer);
1386 ci -> value = suck_s4 ();
1387 cptags [idx] = CONSTANT_Integer;
1394 case CONSTANT_Float: {
1395 constant_float *cf = NEW (constant_float);
1398 count_const_pool_len += sizeof(constant_float);
1401 cf -> value = suck_float ();
1402 cptags [idx] = CONSTANT_Float;
1408 case CONSTANT_Long: {
1409 constant_long *cl = NEW(constant_long);
1412 count_const_pool_len += sizeof(constant_long);
1415 cl -> value = suck_s8 ();
1416 cptags [idx] = CONSTANT_Long;
1420 panic("Long constant exceeds constant pool");
1424 case CONSTANT_Double: {
1425 constant_double *cd = NEW(constant_double);
1428 count_const_pool_len += sizeof(constant_double);
1431 cd -> value = suck_double ();
1432 cptags [idx] = CONSTANT_Double;
1436 panic("Double constant exceeds constant pool");
1440 case CONSTANT_Utf8: {
1442 /* number of bytes in the bytes array (not string-length) */
1443 u4 length = suck_u2();
1444 cptags [idx] = CONSTANT_Utf8;
1445 /* validate the string */
1446 ASSERT_LEFT(length);
1448 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1449 panic("Invalid UTF-8 string");
1450 /* insert utf-string into the utf-symboltable */
1451 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1452 /* skip bytes of the string */
1453 skip_nbytes(length);
1459 error ("Unkown constant type: %d",(int) t);
1467 /* resolve entries in temporary structures */
1469 while (forward_classes) {
1471 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1473 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1474 /* retrieve class from class-table */
1475 cpinfos [forward_classes -> thisindex] = class_new (name);
1477 forward_classes = forward_classes -> next;
1481 while (forward_strings) {
1483 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1485 log_text("forward_string:");
1486 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1488 log_text("\n------------------"); */
1489 /* resolve utf-string */
1490 cptags [forward_strings -> thisindex] = CONSTANT_String;
1491 cpinfos [forward_strings -> thisindex] = text;
1493 forward_strings = forward_strings -> next;
1496 while (forward_nameandtypes) {
1497 constant_nameandtype *cn = NEW (constant_nameandtype);
1500 count_const_pool_len += sizeof(constant_nameandtype);
1503 /* resolve simple name and descriptor */
1504 cn -> name = class_getconstant
1505 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1506 cn -> descriptor = class_getconstant
1507 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1509 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1510 cpinfos [forward_nameandtypes -> thisindex] = cn;
1512 forward_nameandtypes = forward_nameandtypes -> next;
1516 while (forward_fieldmethints) {
1517 constant_nameandtype *nat;
1518 constant_FMIref *fmi = NEW (constant_FMIref);
1521 count_const_pool_len += sizeof(constant_FMIref);
1523 /* resolve simple name and descriptor */
1524 nat = class_getconstant
1525 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1528 log_text("trying to resolve:");
1529 log_text(nat->name->text);
1530 switch(forward_fieldmethints ->tag) {
1531 case CONSTANT_Fieldref:
1532 log_text("CONSTANT_Fieldref");
1534 case CONSTANT_InterfaceMethodref:
1535 log_text("CONSTANT_InterfaceMethodref");
1537 case CONSTANT_Methodref:
1538 log_text("CONSTANT_Methodref");
1542 fmi -> class = class_getconstant
1543 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1544 fmi -> name = nat -> name;
1545 fmi -> descriptor = nat -> descriptor;
1547 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1548 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1550 switch (forward_fieldmethints -> tag) {
1551 case CONSTANT_Fieldref: /* check validity of descriptor */
1552 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1554 case CONSTANT_InterfaceMethodref:
1555 case CONSTANT_Methodref: /* check validity of descriptor */
1556 /* XXX check special names (<init>) */
1557 checkmethoddescriptor (fmi->descriptor);
1561 forward_fieldmethints = forward_fieldmethints -> next;
1565 /* class_showconstantpool(c); */
1567 dump_release (dumpsize);
1571 /********************** Function: class_load ***********************************
1573 Loads everything interesting about a class from the class file. The
1574 'classinfo' structure must have been allocated previously.
1576 The super class and the interfaces implemented by this class need not be
1577 loaded. The link is set later by the function 'class_link'.
1579 The loaded class is removed from the list 'unloadedclasses' and added to
1580 the list 'unlinkedclasses'.
1582 *******************************************************************************/
1584 static int class_load(classinfo *c)
1590 count_class_loads++;
1593 /* output for debugging purposes */
1595 char logtext[MAXLOGTEXT];
1596 sprintf(logtext, "Loading class: ");
1597 utf_sprint(logtext + strlen(logtext), c->name);
1601 /* load classdata, throw exception on error */
1603 if (!suck_start(c->name)) {
1604 throw_noclassdeffounderror_message(c->name);
1608 /* check signature */
1609 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1613 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1614 error("File version %d.%d is not supported", (int) ma, (int) mi);
1619 c->erroneous_state = 0;
1620 c->initializing_thread = 0;
1622 c->classUsed = NOTUSED; /* not used initially CO-RT */
1626 c->flags = suck_u2();
1627 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1629 /* check ACC flags consistency */
1630 if ((c->flags & ACC_INTERFACE) != 0) {
1631 if ((c->flags & ACC_ABSTRACT) == 0)
1632 panic("Interface class not declared abstract");
1633 if ((c->flags & (ACC_FINAL | ACC_SUPER)) != 0)
1634 panic("Interface class has invalid flags");
1638 suck_u2(); /* XXX check it? */
1640 /* retrieve superclass */
1641 if ((i = suck_u2())) {
1642 c->super = class_getconstant(c, i, CONSTANT_Class);
1648 /* retrieve interfaces */
1649 c->interfacescount = suck_u2();
1650 c->interfaces = MNEW(classinfo*, c->interfacescount);
1651 for (i = 0; i < c->interfacescount; i++) {
1653 class_getconstant(c, suck_u2(), CONSTANT_Class);
1657 c->fieldscount = suck_u2();
1658 /* utf_display(c->name);
1659 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1661 c->fields = GCNEW(fieldinfo, c->fieldscount);
1662 for (i = 0; i < c->fieldscount; i++) {
1663 field_load(&(c->fields[i]), c);
1667 c->methodscount = suck_u2();
1668 c->methods = MNEW(methodinfo, c->methodscount);
1669 for (i = 0; i < c->methodscount; i++) {
1670 method_load(&(c->methods[i]), c);
1674 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1675 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1676 count_class_infos += sizeof(methodinfo) * c->methodscount;
1679 /* load variable-length attribute structures */
1680 attribute_load(suck_u2(), c);
1685 /* remove class from list of unloaded classes and
1686 add to list of unlinked classes */
1687 list_remove(&unloadedclasses, c);
1688 list_addlast(&unlinkedclasses, c);
1697 /************** internal Function: class_highestinterface ***********************
1699 Used by the function class_link to determine the amount of memory needed
1700 for the interface table.
1702 *******************************************************************************/
1704 static s4 class_highestinterface(classinfo *c)
1709 if (!(c->flags & ACC_INTERFACE)) {
1710 char logtext[MAXLOGTEXT];
1711 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1712 utf_sprint(logtext + strlen(logtext), c->name);
1713 error("%s",logtext);
1717 for (i = 0; i < c->interfacescount; i++) {
1718 s4 h2 = class_highestinterface(c->interfaces[i]);
1726 /* class_addinterface **********************************************************
1728 Is needed by class_link for adding a VTBL to a class. All interfaces
1729 implemented by ic are added as well.
1731 *******************************************************************************/
1733 static void class_addinterface (classinfo *c, classinfo *ic)
1737 vftbl *vftbl = c->vftbl;
1739 if (i >= vftbl->interfacetablelength)
1740 panic ("Inernal error: interfacetable overflow");
1741 if (vftbl->interfacetable[-i])
1744 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1745 vftbl->interfacevftbllength[i] = 1;
1746 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1747 vftbl->interfacetable[-i][0] = NULL;
1750 vftbl->interfacevftbllength[i] = ic->methodscount;
1751 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1754 count_vftbl_len += sizeof(methodptr) *
1755 (ic->methodscount + (ic->methodscount == 0));
1758 for (j=0; j<ic->methodscount; j++) {
1761 for (m = 0; m < sc->methodscount; m++) {
1762 methodinfo *mi = &(sc->methods[m]);
1763 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1764 vftbl->interfacetable[-i][j] =
1765 vftbl->table[mi->vftblindex];
1775 for (j = 0; j < ic->interfacescount; j++)
1776 class_addinterface(c, ic->interfaces[j]);
1780 /******************* Function: class_new_array *********************************
1782 This function is called by class_new to setup an array class.
1784 *******************************************************************************/
1786 void class_new_array(classinfo *c)
1788 classinfo *comp = NULL;
1792 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1794 /* Array classes are not loaded from classfiles. */
1795 list_remove(&unloadedclasses, c);
1797 /* Check array class name */
1798 namelen = c->name->blength;
1799 if (namelen < 2 || c->name->text[0] != '[')
1800 panic("Invalid array class name");
1802 /* Check the component type */
1803 switch (c->name->text[1]) {
1805 /* c is an array of arrays. We have to create the component class. */
1806 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1810 /* c is an array of objects. */
1811 if (namelen < 4 || c->name->text[namelen - 1] != ';')
1812 panic("Invalid array class name");
1813 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1817 /* Setup the array class */
1818 c->super = class_java_lang_Object;
1819 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1821 c->interfacescount = 2;
1822 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1823 c->interfaces[0] = class_java_lang_Cloneable;
1824 c->interfaces[1] = class_java_io_Serializable;
1826 c->methodscount = 1;
1827 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1830 memset(clone, 0, sizeof(methodinfo));
1831 clone->flags = ACC_PUBLIC; /* XXX protected? */
1832 clone->name = utf_new_char("clone");
1833 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1835 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
1836 clone->monoPoly = MONO; /* XXX should be poly? */
1838 /* XXX: field: length? */
1840 /* The array class has to be linked */
1841 list_addlast(&unlinkedclasses,c);
1844 * Array classes which are created after the other classes have been
1845 * loaded and linked are linked explicitely.
1850 loader_load(c->name); /* XXX handle errors */
1854 /****************** Function: class_link_array *********************************
1856 This function is called by class_link to create the
1857 arraydescriptor for an array class.
1859 This function returns NULL if the array cannot be linked because
1860 the component type has not been linked yet.
1862 *******************************************************************************/
1864 static arraydescriptor *class_link_array(classinfo *c)
1866 classinfo *comp = NULL;
1867 int namelen = c->name->blength;
1868 arraydescriptor *desc;
1871 /* Check the component type */
1872 switch (c->name->text[1]) {
1874 /* c is an array of arrays. */
1875 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1876 if (!comp) panic("Could not find component array class.");
1880 /* c is an array of objects. */
1881 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1882 if (!comp) panic("Could not find component class.");
1886 /* If the component type has not been linked return NULL */
1887 if (comp && !comp->linked)
1890 /* Allocate the arraydescriptor */
1891 desc = NEW(arraydescriptor);
1894 /* c is an array of references */
1895 desc->arraytype = ARRAYTYPE_OBJECT;
1896 desc->componentsize = sizeof(void*);
1897 desc->dataoffset = OFFSET(java_objectarray,data);
1899 compvftbl = comp->vftbl;
1901 panic("Component class has no vftbl");
1902 desc->componentvftbl = compvftbl;
1904 if (compvftbl->arraydesc) {
1905 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1906 if (compvftbl->arraydesc->dimension >= 255)
1907 panic("Creating array of dimension >255");
1908 desc->dimension = compvftbl->arraydesc->dimension + 1;
1909 desc->elementtype = compvftbl->arraydesc->elementtype;
1912 desc->elementvftbl = compvftbl;
1913 desc->dimension = 1;
1914 desc->elementtype = ARRAYTYPE_OBJECT;
1918 /* c is an array of a primitive type */
1919 switch (c->name->text[1]) {
1920 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1921 desc->dataoffset = OFFSET(java_booleanarray,data);
1922 desc->componentsize = sizeof(u1);
1925 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1926 desc->dataoffset = OFFSET(java_bytearray,data);
1927 desc->componentsize = sizeof(u1);
1930 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1931 desc->dataoffset = OFFSET(java_chararray,data);
1932 desc->componentsize = sizeof(u2);
1935 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1936 desc->dataoffset = OFFSET(java_doublearray,data);
1937 desc->componentsize = sizeof(double);
1940 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1941 desc->dataoffset = OFFSET(java_floatarray,data);
1942 desc->componentsize = sizeof(float);
1945 case 'I': desc->arraytype = ARRAYTYPE_INT;
1946 desc->dataoffset = OFFSET(java_intarray,data);
1947 desc->componentsize = sizeof(s4);
1950 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1951 desc->dataoffset = OFFSET(java_longarray,data);
1952 desc->componentsize = sizeof(s8);
1955 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1956 desc->dataoffset = OFFSET(java_shortarray,data);
1957 desc->componentsize = sizeof(s2);
1961 panic("Invalid array class name");
1964 desc->componentvftbl = NULL;
1965 desc->elementvftbl = NULL;
1966 desc->dimension = 1;
1967 desc->elementtype = desc->arraytype;
1974 /********************** Function: class_link ***********************************
1976 Tries to link a class. The super class and every implemented interface must
1977 already have been linked. The function calculates the length in bytes that
1978 an instance of this class requires as well as the VTBL for methods and
1981 If the class can be linked, it is removed from the list 'unlinkedclasses'
1982 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1985 Attention: If cyclical class definitions are encountered, the program gets
1986 into an infinite loop (we'll have to work that out)
1988 *******************************************************************************/
1990 void class_link(classinfo *c)
1992 s4 supervftbllength; /* vftbllegnth of super class */
1993 s4 vftbllength; /* vftbllength of current class */
1994 s4 interfacetablelength; /* interface table length */
1995 classinfo *super = c->super; /* super class */
1996 classinfo *ic, *c2; /* intermediate class variables */
1997 vftbl *v; /* vftbl of current class */
1998 s4 i; /* interface/method/field counter */
1999 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2002 /* check if all superclasses are already linked, if not put c at end of
2003 unlinked list and return. Additionally initialize class fields. */
2005 /* check interfaces */
2007 for (i = 0; i < c->interfacescount; i++) {
2008 ic = c->interfaces[i];
2010 list_remove(&unlinkedclasses, c);
2011 list_addlast(&unlinkedclasses, c);
2016 /* check super class */
2018 if (super == NULL) { /* class java.long.Object */
2020 c->classUsed = USED; /* Object class is always used CO-RT*/
2022 c->instancesize = sizeof(java_objectheader);
2024 vftbllength = supervftbllength = 0;
2026 c->finalizer = NULL;
2029 if (!super->linked) {
2030 list_remove(&unlinkedclasses, c);
2031 list_addlast(&unlinkedclasses, c);
2035 /* handle array classes */
2036 /* The component class must have been linked already. */
2037 if (c->name->text[0] == '[')
2038 if ((arraydesc = class_link_array(c)) == NULL) {
2039 list_remove(&unlinkedclasses, c);
2040 list_addlast(&unlinkedclasses, c);
2044 /* Don't allow extending final classes */
2045 if ((super->flags & ACC_FINAL) != 0)
2046 panic("Trying to extend final class");
2048 if (c->flags & ACC_INTERFACE)
2049 c->index = interfaceindex++;
2051 c->index = super->index + 1;
2053 c->instancesize = super->instancesize;
2055 vftbllength = supervftbllength = super->vftbl->vftbllength;
2057 c->finalizer = super->finalizer;
2062 char logtext[MAXLOGTEXT];
2063 sprintf(logtext, "Linking Class: ");
2064 utf_sprint(logtext + strlen(logtext), c->name );
2068 /* compute vftbl length */
2070 for (i = 0; i < c->methodscount; i++) {
2071 methodinfo *m = &(c->methods[i]);
2073 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2074 classinfo *sc = super;
2077 for (j = 0; j < sc->methodscount; j++) {
2078 if (method_canoverwrite(m, &(sc->methods[j]))) {
2079 if ((sc->methods[j].flags & ACC_FINAL) != 0)
2080 panic("Trying to overwrite final method");
2081 m->vftblindex = sc->methods[j].vftblindex;
2082 goto foundvftblindex;
2087 m->vftblindex = (vftbllength++);
2093 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2096 /* compute interfacetable length */
2098 interfacetablelength = 0;
2101 for (i = 0; i < c2->interfacescount; i++) {
2102 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2103 if (h > interfacetablelength)
2104 interfacetablelength = h;
2109 /* allocate virtual function table */
2111 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2112 (vftbllength - 1) + sizeof(methodptr*) *
2113 (interfacetablelength - (interfacetablelength > 0)));
2114 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2115 (interfacetablelength > 1));
2116 c->header.vftbl = c->vftbl = v;
2118 v->vftbllength = vftbllength;
2119 v->interfacetablelength = interfacetablelength;
2120 v->arraydesc = arraydesc;
2122 /* store interface index in vftbl */
2123 if (c->flags & ACC_INTERFACE)
2124 v->baseval = -(c->index);
2126 /* copy virtual function table of super class */
2128 for (i = 0; i < supervftbllength; i++)
2129 v->table[i] = super->vftbl->table[i];
2131 /* add method stubs into virtual function table */
2133 for (i = 0; i < c->methodscount; i++) {
2134 methodinfo *m = &(c->methods[i]);
2135 if (!(m->flags & ACC_STATIC)) {
2136 v->table[m->vftblindex] = m->stubroutine;
2140 /* compute instance size and offset of each field */
2142 for (i = 0; i < c->fieldscount; i++) {
2144 fieldinfo *f = &(c->fields[i]);
2146 if (!(f->flags & ACC_STATIC) ) {
2147 dsize = desc_typesize(f->descriptor);
2148 c->instancesize = ALIGN(c->instancesize, dsize);
2149 f->offset = c->instancesize;
2150 c->instancesize += dsize;
2154 /* initialize interfacetable and interfacevftbllength */
2156 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2159 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2162 for (i = 0; i < interfacetablelength; i++) {
2163 v->interfacevftbllength[i] = 0;
2164 v->interfacetable[-i] = NULL;
2167 /* add interfaces */
2169 for (c2 = c; c2 != NULL; c2 = c2->super)
2170 for (i = 0; i < c2->interfacescount; i++) {
2171 class_addinterface(c, c2->interfaces[i]);
2174 /* add finalizer method (not for java.lang.Object) */
2176 if (super != NULL) {
2178 static utf *finame = NULL;
2179 static utf *fidesc = NULL;
2182 finame = utf_finalize;
2184 fidesc = utf_fidesc;
2186 fi = class_findmethod(c, finame, fidesc);
2188 if (!(fi->flags & ACC_STATIC)) {
2198 list_remove(&unlinkedclasses, c);
2199 list_addlast(&linkedclasses, c);
2203 /******************* Function: class_freepool **********************************
2205 Frees all resources used by this classes Constant Pool.
2207 *******************************************************************************/
2209 static void class_freecpool (classinfo *c)
2215 for (idx=0; idx < c->cpcount; idx++) {
2216 tag = c->cptags[idx];
2217 info = c->cpinfos[idx];
2221 case CONSTANT_Fieldref:
2222 case CONSTANT_Methodref:
2223 case CONSTANT_InterfaceMethodref:
2224 FREE (info, constant_FMIref);
2226 case CONSTANT_Integer:
2227 FREE (info, constant_integer);
2229 case CONSTANT_Float:
2230 FREE (info, constant_float);
2233 FREE (info, constant_long);
2235 case CONSTANT_Double:
2236 FREE (info, constant_double);
2238 case CONSTANT_NameAndType:
2239 FREE (info, constant_nameandtype);
2245 MFREE (c -> cptags, u1, c -> cpcount);
2246 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2250 /*********************** Function: class_free **********************************
2252 Frees all resources used by the class.
2254 *******************************************************************************/
2256 static void class_free(classinfo *c)
2263 MFREE(c->interfaces, classinfo*, c->interfacescount);
2265 for (i = 0; i < c->fieldscount; i++)
2266 field_free(&(c->fields[i]));
2268 for (i = 0; i < c->methodscount; i++)
2269 method_free(&(c->methods[i]));
2270 MFREE(c->methods, methodinfo, c->methodscount);
2272 if ((v = c->vftbl) != NULL) {
2274 mem_free(v->arraydesc,sizeof(arraydescriptor));
2276 for (i = 0; i < v->interfacetablelength; i++) {
2277 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2279 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2281 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2282 sizeof(methodptr*) * (v->interfacetablelength -
2283 (v->interfacetablelength > 0));
2284 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2285 (v->interfacetablelength > 1));
2289 if (c->innerclasscount)
2290 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2292 /* if (c->classvftbl)
2293 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2299 /************************* Function: class_findfield ***************************
2301 Searches a 'classinfo' structure for a field having the given name and
2304 *******************************************************************************/
2306 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2310 for (i = 0; i < c->fieldscount; i++) {
2311 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2312 return &(c->fields[i]);
2315 panic("Can not find field given in CONSTANT_Fieldref");
2317 /* keep compiler happy */
2322 /************************* Function: class_findmethod **************************
2324 Searches a 'classinfo' structure for a method having the given name and
2325 type and returns the index in the class info structure.
2326 If type is NULL, it is ignored.
2328 *******************************************************************************/
2330 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2333 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2335 int buffer_len, pos;
2337 #ifdef JOWENN_DEBUG1
2340 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2342 buffer = MNEW(char, buffer_len);
2344 strcpy(buffer, "class_findmethod: method:");
2345 utf_sprint(buffer + strlen(buffer), name);
2346 strcpy(buffer + strlen(buffer), ", desc: ");
2347 utf_sprint(buffer + strlen(buffer), desc);
2348 strcpy(buffer + strlen(buffer), ", classname: ");
2349 utf_sprint(buffer + strlen(buffer), c->name);
2353 MFREE(buffer, char, buffer_len);
2355 for (i = 0; i < c->methodscount; i++) {
2356 #ifdef JOWENN_DEBUG2
2358 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2360 buffer = MNEW(char, buffer_len);
2362 strcpy(buffer, "class_findmethod: comparing to method:");
2363 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2364 strcpy(buffer + strlen(buffer), ", desc: ");
2365 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2369 MFREE(buffer, char, buffer_len);
2373 if ((c->methods[i].name == name) && ((desc == NULL) ||
2374 (c->methods[i].descriptor == desc))) {
2379 #ifdef JOWENN_DEBUG2
2380 class_showconstantpool(c);
2381 log_text("class_findmethod: returning NULL");
2388 /************************* Function: class_findmethod **************************
2390 Searches a 'classinfo' structure for a method having the given name and
2392 If type is NULL, it is ignored.
2394 *******************************************************************************/
2396 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2400 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2402 int buffer_len, pos;
2404 #ifdef JOWENN_DEBUG1
2407 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2409 buffer = MNEW(char, buffer_len);
2411 strcpy(buffer, "class_findmethod: method:");
2412 utf_sprint(buffer + strlen(buffer), name);
2413 strcpy(buffer + strlen(buffer), ", desc: ");
2414 utf_sprint(buffer + strlen(buffer), desc);
2415 strcpy(buffer + strlen(buffer), ", classname: ");
2416 utf_sprint(buffer + strlen(buffer), c->name);
2420 MFREE(buffer, char, buffer_len);
2422 for (i = 0; i < c->methodscount; i++) {
2423 #ifdef JOWENN_DEBUG2
2425 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2427 buffer = MNEW(char, buffer_len);
2429 strcpy(buffer, "class_findmethod: comparing to method:");
2430 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2431 strcpy(buffer + strlen(buffer), ", desc: ");
2432 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2436 MFREE(buffer, char, buffer_len);
2439 if ((c->methods[i].name == name) && ((desc == NULL) ||
2440 (c->methods[i].descriptor == desc))) {
2441 return &(c->methods[i]);
2444 #ifdef JOWENN_DEBUG2
2445 class_showconstantpool(c);
2446 log_text("class_findmethod: returning NULL");
2451 s4 idx=class_findmethodIndex(c, name, desc);
2452 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2453 if (idx == -1) return NULL;
2455 return &(c->methods[idx]);
2459 /*********************** Function: class_fetchmethod **************************
2461 like class_findmethod, but aborts with an error if the method is not found
2463 *******************************************************************************/
2465 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2468 mi = class_findmethod(c, name, desc);
2471 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2472 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2473 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2474 panic("Method not found");
2481 /************************* Function: class_findmethod_approx ******************
2483 like class_findmethod but ignores the return value when comparing the
2486 *******************************************************************************/
2488 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2492 for (i = 0; i < c->methodscount; i++) {
2493 if (c->methods[i].name == name) {
2494 utf *meth_descr = c->methods[i].descriptor;
2498 return &(c->methods[i]);
2500 if (desc->blength <= meth_descr->blength) {
2501 /* current position in utf text */
2502 char *desc_utf_ptr = desc->text;
2503 char *meth_utf_ptr = meth_descr->text;
2504 /* points behind utf strings */
2505 char *desc_end = utf_end(desc);
2506 char *meth_end = utf_end(meth_descr);
2509 /* compare argument types */
2510 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2512 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2513 break; /* no match */
2516 return &(c->methods[i]); /* all parameter types equal */
2526 /***************** Function: class_resolvemethod_approx ***********************
2528 Searches a class and every super class for a method (without paying
2529 attention to the return value)
2531 *******************************************************************************/
2533 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2536 /* search for method (ignore returntype) */
2537 methodinfo *m = class_findmethod_approx(c, name, desc);
2540 /* search superclass */
2548 /************************* Function: class_resolvemethod ***********************
2550 Searches a class and every super class for a method.
2552 *******************************************************************************/
2554 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2557 methodinfo *m = class_findmethod(c, name, desc);
2559 /* search superclass */
2567 /************************* Function: class_issubclass **************************
2569 Checks if sub is a descendant of super.
2571 *******************************************************************************/
2573 bool class_issubclass(classinfo *sub, classinfo *super)
2576 if (!sub) return false;
2577 if (sub == super) return true;
2583 /****************** Initialization function for classes ******************
2585 In Java, every class can have a static initialization function. This
2586 function has to be called BEFORE calling other methods or accessing static
2589 *******************************************************************************/
2591 void class_init(classinfo *c)
2599 if (!makeinitializations)
2604 c->initialized = true;
2607 count_class_inits++;
2611 class_init(c->super);
2612 for (i = 0; i < c->interfacescount; i++)
2613 class_init(c->interfaces[i]); /* real */
2615 m = class_findmethod(c, utf_clinit, utf_fidesc);
2618 char logtext[MAXLOGTEXT];
2619 sprintf(logtext, "Class ");
2620 utf_sprint(logtext + strlen(logtext), c->name);
2621 sprintf(logtext + strlen(logtext), " has no initializer");
2624 /* goto callinitialize;*/
2628 if (!(m->flags & ACC_STATIC))
2629 panic("Class initializer is not static!");
2632 char logtext[MAXLOGTEXT];
2633 sprintf(logtext, "Starting initializer for class: ");
2634 utf_sprint(logtext + strlen(logtext), c->name);
2643 /* now call the initializer */
2644 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2647 assert(blockInts == 0);
2651 /* we have to throw an exception */
2653 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2654 printf("Caused by: ");
2655 utf_display(exceptionptr->vftbl->class->name);
2662 char logtext[MAXLOGTEXT];
2663 sprintf(logtext, "Finished initializer for class: ");
2664 utf_sprint(logtext + strlen(logtext), c->name);
2668 if (c->name == utf_systemclass) {
2669 /* class java.lang.System requires explicit initialization */
2672 printf("#### Initializing class System");
2674 /* find initializing method */
2675 m = class_findmethod(c,
2676 utf_initsystemclass,
2680 /* no method found */
2681 /* printf("initializeSystemClass failed"); */
2690 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2693 assert(blockInts == 0);
2698 printf("#### initializeSystemClass has thrown: ");
2699 utf_display(exceptionptr->vftbl->class->name);
2707 /********* Function: find_class_method_constant *********/
2709 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2714 for (i=0; i<c->cpcount; i++) {
2716 e = c -> cpinfos [i];
2719 switch (c -> cptags [i]) {
2720 case CONSTANT_Methodref:
2722 constant_FMIref *fmi = e;
2723 if ( (fmi->class->name == c1)
2724 && (fmi->name == m1)
2725 && (fmi->descriptor == d1)) {
2732 case CONSTANT_InterfaceMethodref:
2734 constant_FMIref *fmi = e;
2735 if ( (fmi->class->name == c1)
2736 && (fmi->name == m1)
2737 && (fmi->descriptor == d1)) {
2751 void class_showconstanti(classinfo *c, int ii)
2757 printf ("#%d: ", (int) i);
2759 switch (c->cptags [i]) {
2760 case CONSTANT_Class:
2761 printf("Classreference -> ");
2762 utf_display(((classinfo*)e)->name);
2765 case CONSTANT_Fieldref:
2766 printf("Fieldref -> "); goto displayFMIi;
2767 case CONSTANT_Methodref:
2768 printf("Methodref -> "); goto displayFMIi;
2769 case CONSTANT_InterfaceMethodref:
2770 printf("InterfaceMethod -> "); goto displayFMIi;
2773 constant_FMIref *fmi = e;
2774 utf_display(fmi->class->name);
2776 utf_display(fmi->name);
2778 utf_display(fmi->descriptor);
2782 case CONSTANT_String:
2783 printf("String -> ");
2786 case CONSTANT_Integer:
2787 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2789 case CONSTANT_Float:
2790 printf("Float -> %f", ((constant_float*)e)->value);
2792 case CONSTANT_Double:
2793 printf("Double -> %f", ((constant_double*)e)->value);
2797 u8 v = ((constant_long*)e)->value;
2799 printf("Long -> %ld", (long int) v);
2801 printf("Long -> HI: %ld, LO: %ld\n",
2802 (long int) v.high, (long int) v.low);
2806 case CONSTANT_NameAndType:
2808 constant_nameandtype *cnt = e;
2809 printf("NameAndType: ");
2810 utf_display(cnt->name);
2812 utf_display(cnt->descriptor);
2820 panic("Invalid type of ConstantPool-Entry");
2827 void class_showconstantpool (classinfo *c)
2832 printf ("---- dump of constant pool ----\n");
2834 for (i=0; i<c->cpcount; i++) {
2835 printf ("#%d: ", (int) i);
2837 e = c -> cpinfos [i];
2840 switch (c -> cptags [i]) {
2841 case CONSTANT_Class:
2842 printf ("Classreference -> ");
2843 utf_display ( ((classinfo*)e) -> name );
2846 case CONSTANT_Fieldref:
2847 printf ("Fieldref -> "); goto displayFMI;
2848 case CONSTANT_Methodref:
2849 printf ("Methodref -> "); goto displayFMI;
2850 case CONSTANT_InterfaceMethodref:
2851 printf ("InterfaceMethod -> "); goto displayFMI;
2854 constant_FMIref *fmi = e;
2855 utf_display ( fmi->class->name );
2857 utf_display ( fmi->name);
2859 utf_display ( fmi->descriptor );
2863 case CONSTANT_String:
2864 printf ("String -> ");
2867 case CONSTANT_Integer:
2868 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2870 case CONSTANT_Float:
2871 printf ("Float -> %f", ((constant_float*)e) -> value);
2873 case CONSTANT_Double:
2874 printf ("Double -> %f", ((constant_double*)e) -> value);
2878 u8 v = ((constant_long*)e) -> value;
2880 printf ("Long -> %ld", (long int) v);
2882 printf ("Long -> HI: %ld, LO: %ld\n",
2883 (long int) v.high, (long int) v.low);
2887 case CONSTANT_NameAndType:
2889 constant_nameandtype *cnt = e;
2890 printf ("NameAndType: ");
2891 utf_display (cnt->name);
2893 utf_display (cnt->descriptor);
2897 printf ("Utf8 -> ");
2901 panic ("Invalid type of ConstantPool-Entry");
2911 /********** Function: class_showmethods (debugging only) *************/
2913 void class_showmethods (classinfo *c)
2917 printf ("--------- Fields and Methods ----------------\n");
2918 printf ("Flags: "); printflags (c->flags); printf ("\n");
2920 printf ("This: "); utf_display (c->name); printf ("\n");
2922 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2924 printf ("Index: %d\n", c->index);
2926 printf ("interfaces:\n");
2927 for (i=0; i < c-> interfacescount; i++) {
2929 utf_display (c -> interfaces[i] -> name);
2930 printf (" (%d)\n", c->interfaces[i] -> index);
2933 printf ("fields:\n");
2934 for (i=0; i < c -> fieldscount; i++) {
2935 field_display (&(c -> fields[i]));
2938 printf ("methods:\n");
2939 for (i=0; i < c -> methodscount; i++) {
2940 methodinfo *m = &(c->methods[i]);
2941 if ( !(m->flags & ACC_STATIC))
2942 printf ("vftblindex: %d ", m->vftblindex);
2944 method_display ( m );
2948 printf ("Virtual function table:\n");
2949 for (i=0; i<c->vftbl->vftbllength; i++) {
2950 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2957 /******************************************************************************/
2958 /******************* General functions for the class loader *******************/
2959 /******************************************************************************/
2961 /********************* Function: loader_load ***********************************
2963 Loads and links the class desired class and each class and interface
2965 Returns: a pointer to this class
2967 *******************************************************************************/
2969 static int loader_load_running = 0;
2971 classinfo *loader_load(utf *topname)
2977 classinfo *notlinkable;
2979 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2980 pthread_mutex_lock(&compiler_mutex);
2983 /* avoid recursive calls */
2984 if (loader_load_running)
2985 return class_new(topname);
2987 loader_load_running++;
2992 starttime = getcputime();
2994 top = class_new(topname);
2997 while ((c = list_first(&unloadedclasses))) {
2998 if (!class_load(c)) {
3000 dolog("Failed to load class");
3001 list_remove(&unloadedclasses, c);
3008 dolog("Linking...");
3010 /* XXX added a hack to break infinite linking loops. A better
3011 * linking algorithm would be nice. -Edwin */
3013 while ((c = list_first(&unlinkedclasses))) {
3018 else if (notlinkable == c) {
3019 /* We tried to link this class for the second time and
3020 * no other classes were linked in between, so we are
3024 dolog("Cannot resolve linking dependencies");
3027 throw_linkageerror_message(c->name);
3035 dolog("Linking done.");
3038 loader_compute_subclasses();
3041 if (getloadingtime) {
3042 stoptime = getcputime();
3043 loadingtime += (stoptime - starttime);
3047 loader_load_running--;
3049 /* check if a former loader_load call tried to load/link the class and
3050 failed. This is needed because the class didn't appear in the
3051 undloadclasses or unlinkedclasses list during this class. */
3054 if (linkverbose) dolog("Failed to load class (former call)");
3055 throw_noclassdeffounderror_message(top->name);
3058 } else if (!top->linked) {
3060 dolog("Failed to link class (former call)");
3061 throw_linkageerror_message(top->name);
3068 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3069 pthread_mutex_unlock(&compiler_mutex);
3072 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
3078 /****************** Function: loader_load_sysclass ****************************
3080 Loads and links the class desired class and each class and interface
3083 The pointer to the classinfo is stored in *top if top != NULL.
3084 The pointer is also returned.
3086 If the class could not be loaded the function aborts with an error.
3088 *******************************************************************************/
3090 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3094 if ((cls = loader_load(topname)) == NULL) {
3095 log_plain("Could not load important system class: ");
3096 log_plain_utf(topname);
3098 panic("Could not load important system class");
3101 if (top) *top = cls;
3107 /**************** function: create_primitive_classes ***************************
3109 create classes representing primitive types
3111 ********************************************************************************/
3114 void create_primitive_classes()
3118 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3119 /* create primitive class */
3120 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3121 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3122 c -> impldBy = NULL;
3124 /* prevent loader from loading primitive class */
3125 list_remove (&unloadedclasses, c);
3127 /* add to unlinked classes */
3128 list_addlast (&unlinkedclasses, c);
3129 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3132 primitivetype_table[i].class_primitive = c;
3134 /* create class for wrapping the primitive type */
3135 primitivetype_table[i].class_wrap =
3136 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3137 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3138 primitivetype_table[i].class_wrap -> impldBy = NULL;
3140 /* create the primitive array class */
3141 if (primitivetype_table[i].arrayname) {
3142 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3143 primitivetype_table[i].arrayclass = c;
3145 if (!c->linked) class_link(c);
3146 primitivetype_table[i].arrayvftbl = c->vftbl;
3151 /**************** function: class_primitive_from_sig ***************************
3153 return the primitive class indicated by the given signature character
3155 If the descriptor does not indicate a valid primitive type the
3156 return value is NULL.
3158 ********************************************************************************/
3160 classinfo *class_primitive_from_sig(char sig)
3163 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3164 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3165 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3166 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3167 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3168 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3169 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3170 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3171 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3176 /****************** function: class_from_descriptor ****************************
3178 return the class indicated by the given descriptor
3180 utf_ptr....first character of descriptor
3181 end_ptr....first character after the end of the string
3182 next.......if non-NULL, *next is set to the first character after
3183 the descriptor. (Undefined if an error occurs.)
3185 mode.......a combination (binary or) of the following flags:
3187 (Flags marked with * are the default settings.)
3189 What to do if a reference type descriptor is parsed successfully:
3191 CLASSLOAD_SKIP...skip it and return something != NULL
3192 * CLASSLOAD_NEW....get classinfo * via class_new
3193 CLASSLOAD_LOAD...get classinfo * via loader_load
3195 How to handle primitive types:
3197 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3198 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3200 How to handle "V" descriptors:
3202 * CLASSLOAD_VOID.....handle it like other primitive types
3203 CLASSLOAD_NOVOID...treat it as an error
3205 How to deal with extra characters after the end of the
3208 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3209 CLASSLOAD_CHECKEND.....treat them as an error
3211 How to deal with errors:
3213 * CLASSLOAD_PANIC....abort execution with an error message
3214 CLASSLOAD_NOPANIC..return NULL on error
3216 ********************************************************************************/
3218 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3219 char **next, int mode)
3221 char *start = utf_ptr;
3225 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3227 if (mode & CLASSLOAD_CHECKEND)
3228 error |= (utf_ptr != end_ptr);
3231 if (next) *next = utf_ptr;
3235 if (mode & CLASSLOAD_NOVOID)
3246 return (mode & CLASSLOAD_NULLPRIMITIVE)
3248 : class_primitive_from_sig(*start);
3255 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3256 name = utf_new(start,utf_ptr-start);
3257 return (mode & CLASSLOAD_LOAD)
3258 ? loader_load(name) : class_new(name); /* XXX */
3262 /* An error occurred */
3263 if (mode & CLASSLOAD_NOPANIC)
3266 log_plain("Invalid descriptor at beginning of '");
3267 log_plain_utf(utf_new(start, end_ptr-start));
3271 panic("Invalid descriptor");
3273 /* keep compiler happy */
3278 /******************* function: type_from_descriptor ****************************
3280 return the basic type indicated by the given descriptor
3282 This function parses a descriptor and returns its basic type as
3283 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3285 cls...if non-NULL the referenced variable is set to the classinfo *
3286 returned by class_from_descriptor.
3288 For documentation of the arguments utf_ptr, end_ptr, next and mode
3289 see class_from_descriptor. The only difference is that
3290 type_from_descriptor always uses CLASSLOAD_PANIC.
3292 ********************************************************************************/
3294 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3295 char **next, int mode)
3298 if (!cls) cls = &mycls;
3299 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3316 return TYPE_ADDRESS;
3320 /*************** function: create_pseudo_classes *******************************
3322 create pseudo classes used by the typechecker
3324 ********************************************************************************/
3326 static void create_pseudo_classes()
3328 /* pseudo class for Arraystubs (extends java.lang.Object) */
3330 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3331 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3333 pseudo_class_Arraystub->super = class_java_lang_Object;
3334 pseudo_class_Arraystub->interfacescount = 2;
3335 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3336 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3337 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3339 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3340 class_link(pseudo_class_Arraystub);
3342 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3344 /* pseudo class representing the null type */
3346 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3347 list_remove(&unloadedclasses, pseudo_class_Null);
3349 pseudo_class_Null->super = class_java_lang_Object;
3351 list_addlast(&unlinkedclasses, pseudo_class_Null);
3352 class_link(pseudo_class_Null);
3354 /* pseudo class representing new uninitialized objects */
3356 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3357 list_remove(&unloadedclasses, pseudo_class_New);
3359 pseudo_class_New->super = class_java_lang_Object;
3361 list_addlast(&unlinkedclasses, pseudo_class_New);
3362 class_link(pseudo_class_New);
3366 /********************** Function: loader_init **********************************
3368 Initializes all lists and loads all classes required for the system or the
3371 *******************************************************************************/
3373 void loader_init(u1 *stackbottom)
3377 log_text("Entering loader_init");
3379 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3380 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3381 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3383 /* create utf-symbols for pointer comparison of frequently used strings */
3384 utf_innerclasses = utf_new_char("InnerClasses");
3385 utf_constantvalue = utf_new_char("ConstantValue");
3386 utf_code = utf_new_char("Code");
3387 utf_finalize = utf_new_char("finalize");
3388 utf_fidesc = utf_new_char("()V");
3389 utf_clinit = utf_new_char("<clinit>");
3390 utf_initsystemclass = utf_new_char("initializeSystemClass");
3391 utf_systemclass = utf_new_char("java/lang/System");
3392 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3393 utf_initialize = utf_new_char("initialize");
3394 utf_initializedesc = utf_new_char("(I)V");
3396 utf_vmclass = utf_new_char("java/lang/VMClass");
3398 /* create some important classes */
3399 /* These classes have to be created now because the classinfo
3400 * pointers are used in the loading code.
3402 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3403 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3404 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3405 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3407 if (verbose) log_text("loader_init: java/lang/Object");
3408 /* load the classes which were created above */
3409 loader_load_sysclass(NULL, class_java_lang_Object->name);
3411 loader_inited = 1; /*JOWENN*/
3413 loader_load_sysclass(&class_java_lang_Throwable,
3414 utf_new_char("java/lang/Throwable"));
3416 if (verbose) log_text("loader_init: loader_load: java/lang/ClassCastException");
3417 loader_load_sysclass(&class_java_lang_ClassCastException,
3418 utf_new_char ("java/lang/ClassCastException"));
3419 loader_load_sysclass(&class_java_lang_NullPointerException,
3420 utf_new_char ("java/lang/NullPointerException"));
3421 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3422 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3423 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3424 utf_new_char ("java/lang/NegativeArraySizeException"));
3425 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3426 utf_new_char ("java/lang/OutOfMemoryError"));
3427 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3428 utf_new_char ("java/lang/ArrayStoreException"));
3429 loader_load_sysclass(&class_java_lang_ArithmeticException,
3430 utf_new_char ("java/lang/ArithmeticException"));
3431 loader_load_sysclass(&class_java_lang_ThreadDeath,
3432 utf_new_char ("java/lang/ThreadDeath"));
3434 /* create classes representing primitive types */
3435 create_primitive_classes();
3437 /* create classes used by the typechecker */
3438 create_pseudo_classes();
3440 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3441 stringtable_update();
3448 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3449 proto_java_lang_ClassCastException =
3450 builtin_new(class_java_lang_ClassCastException);
3452 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3454 proto_java_lang_NullPointerException =
3455 builtin_new(class_java_lang_NullPointerException);
3456 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3458 proto_java_lang_ArrayIndexOutOfBoundsException =
3459 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3461 proto_java_lang_NegativeArraySizeException =
3462 builtin_new(class_java_lang_NegativeArraySizeException);
3464 proto_java_lang_OutOfMemoryError =
3465 builtin_new(class_java_lang_OutOfMemoryError);
3467 proto_java_lang_ArithmeticException =
3468 builtin_new(class_java_lang_ArithmeticException);
3470 proto_java_lang_ArrayStoreException =
3471 builtin_new(class_java_lang_ArrayStoreException);
3473 proto_java_lang_ThreadDeath =
3474 builtin_new(class_java_lang_ThreadDeath);
3480 /********************* Function: loader_initclasses ****************************
3482 Initializes all loaded but uninitialized classes
3484 *******************************************************************************/
3487 /* XXX TWISTI: i think we do not need this */
3488 void loader_initclasses ()
3492 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3493 pthread_mutex_lock(&compiler_mutex);
3496 intsDisable(); /* schani */
3498 if (makeinitializations) {
3499 c = list_first(&linkedclasses);
3502 c = list_next(&linkedclasses, c);
3506 intsRestore(); /* schani */
3508 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3509 pthread_mutex_unlock(&compiler_mutex);
3515 static void loader_compute_class_values(classinfo *c)
3519 c->vftbl->baseval = ++classvalue;
3522 while (subs != NULL) {
3523 loader_compute_class_values(subs);
3524 subs = subs->nextsub;
3526 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3531 for (i = 0; i < c->index; i++)
3533 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3534 utf_display(c->name);
3541 void loader_compute_subclasses()
3545 intsDisable(); /* schani */
3547 c = list_first(&linkedclasses);
3549 if (!(c->flags & ACC_INTERFACE)) {
3553 c = list_next(&linkedclasses, c);
3556 c = list_first(&linkedclasses);
3558 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3559 c->nextsub = c->super->sub;
3562 c = list_next(&linkedclasses, c);
3566 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3569 loader_compute_class_values(class_java_lang_Object);
3570 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3574 intsRestore(); /* schani */
3578 /******************** function classloader_buffer ******************************
3580 sets buffer for reading classdata
3582 *******************************************************************************/
3584 void classload_buffer(u1 *buf, int len)
3587 classbuffer_size = len;
3588 classbuf_pos = buf - 1;
3592 /******************** Function: loader_close ***********************************
3596 *******************************************************************************/
3602 while ((c = list_first(&unloadedclasses))) {
3603 list_remove(&unloadedclasses, c);
3606 while ((c = list_first(&unlinkedclasses))) {
3607 list_remove(&unlinkedclasses, c);
3610 while ((c = list_first(&linkedclasses))) {
3611 list_remove(&linkedclasses, c);
3618 * These are local overrides for various environment variables in Emacs.
3619 * Please do not remove this and leave it at the end of the file, where
3620 * Emacs will automagically detect them.
3621 * ---------------------------------------------------------------------
3624 * indent-tabs-mode: t