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 959 2004-03-14 23:39:31Z twisti $
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
54 #include "nat/java_lang_Throwable.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_exceptions; /* Exceptions */
89 static utf *utf_linenumbertable; /* LineNumberTable */
90 static utf *utf_finalize; /* finalize */
91 static utf *utf_fidesc; /* ()V changed */
92 static utf *utf_init; /* <init> */
93 static utf *utf_clinit; /* <clinit> */
94 static utf *utf_initsystemclass; /* initializeSystemClass */
95 static utf *utf_systemclass; /* java/lang/System */
96 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
97 static utf *utf_vmclass; /* java/lang/VMClassLoader */
98 static utf *utf_initialize;
99 static utf *utf_initializedesc;
100 static utf *utf_java_lang_Object; /* java/lang/Object */
113 /* important system classes ***************************************************/
115 classinfo *class_java_lang_Object;
116 classinfo *class_java_lang_String;
118 classinfo *class_java_lang_Throwable;
119 classinfo *class_java_lang_Cloneable;
120 classinfo *class_java_io_Serializable;
122 /* Pseudo classes for the typechecker */
123 classinfo *pseudo_class_Arraystub = NULL;
124 classinfo *pseudo_class_Null = NULL;
125 classinfo *pseudo_class_New = NULL;
126 vftbl *pseudo_class_Arraystub_vftbl = NULL;
129 /* These are made static so they cannot be used for throwing in native */
131 static classinfo *class_java_lang_ClassCastException;
132 static classinfo *class_java_lang_NullPointerException;
133 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
134 static classinfo *class_java_lang_NegativeArraySizeException;
135 static classinfo *class_java_lang_OutOfMemoryError;
136 static classinfo *class_java_lang_ArithmeticException;
137 static classinfo *class_java_lang_ArrayStoreException;
138 static classinfo *class_java_lang_ThreadDeath;
140 utf *array_packagename = NULL;
142 static int loader_inited = 0;
145 /********************************************************************
146 list of classpath entries (either filesystem directories or
148 ********************************************************************/
149 static classpath_info *classpath_entries=0;
152 /******************************************************************************
154 structure for primitive classes: contains the class for wrapping the
155 primitive type, the primitive class, the name of the class for wrapping,
156 the one character type signature and the name of the primitive class
158 ******************************************************************************/
160 /* CAUTION: Don't change the order of the types. This table is indexed
161 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
163 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
164 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
165 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
166 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
167 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
168 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
169 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
170 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
171 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
172 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
176 /* instances of important system classes **************************************/
178 java_objectheader *proto_java_lang_ClassCastException;
179 java_objectheader *proto_java_lang_NullPointerException;
180 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
181 java_objectheader *proto_java_lang_NegativeArraySizeException;
182 java_objectheader *proto_java_lang_OutOfMemoryError;
183 java_objectheader *proto_java_lang_ArithmeticException;
184 java_objectheader *proto_java_lang_ArrayStoreException;
185 java_objectheader *proto_java_lang_ThreadDeath;
187 /************* functions for reading classdata *********************************
189 getting classdata in blocks of variable size
190 (8,16,32,64-bit integer or float)
192 *******************************************************************************/
194 static char *classpath = ""; /* searchpath for classfiles */
195 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
196 static u1 *classbuf_pos; /* current position in classfile buffer */
197 static int classbuffer_size; /* size of classfile-data */
199 /* assert that at least <len> bytes are left to read */
200 /* <len> is limited to the range of non-negative s4 values */
201 #define ASSERT_LEFT(len) \
202 do {if ( ((s4)(len)) < 0 \
203 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
204 panic("Unexpected end of classfile"); } while(0)
206 /* transfer block of classfile data into a buffer */
208 #define suck_nbytes(buffer,len) \
209 do {ASSERT_LEFT(len); \
210 memcpy(buffer,classbuf_pos+1,len); \
211 classbuf_pos+=len;} while (0)
213 /* skip block of classfile data */
215 #define skip_nbytes(len) \
216 do {ASSERT_LEFT(len); \
217 classbuf_pos+=len;} while(0)
223 return *++classbuf_pos;
231 return ((u2) a << 8) + (u2) b;
241 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
244 #define suck_s8() (s8) suck_u8()
245 #define suck_s2() (s2) suck_u2()
246 #define suck_s4() (s4) suck_u4()
247 #define suck_s1() (s1) suck_u1()
250 /* get u8 from classfile data */
257 return (hi << 32) + lo;
267 /* get float from classfile data */
268 static float suck_float()
275 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
276 memcpy((u1*) (&f), buffer, 4);
278 suck_nbytes((u1*) (&f), 4);
281 PANICIF (sizeof(float) != 4, "Incompatible float-format");
287 /* get double from classfile data */
288 static double suck_double()
295 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
296 memcpy((u1*) (&d), buffer, 8);
298 suck_nbytes((u1*) (&d), 8);
301 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
307 /************************** function suck_init *********************************
309 called once at startup, sets the searchpath for the classfiles
311 *******************************************************************************/
313 void suck_init(char *cpath)
320 union classpath_info *tmp;
321 union classpath_info *insertAfter=0;
326 if (classpath_entries) panic("suck_init should be called only once");
327 for(start=classpath;(*start)!='\0';) {
328 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
331 filenamelen=(end-start);
365 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
366 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
367 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
370 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
371 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
372 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
377 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
379 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
380 strncpy(filename,start,filenamelen);
381 filename[filenamelen+1]='\0';
386 unzFile uf=unzOpen(filename);
388 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
389 tmp->archive.type=CLASSPATH_ARCHIVE;
395 panic("Zip/JAR not supported");
399 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
400 tmp->filepath.type=CLASSPATH_PATH;
401 tmp->filepath.next=0;
402 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
403 filename[filenamelen]='/';
404 filename[filenamelen+1]='\0';
408 tmp->filepath.filename=filename;
409 tmp->filepath.pathlen=filenamelen;
415 insertAfter->filepath.next=tmp;
417 classpath_entries=tmp;
422 if ((*end)==':') start=end+1; else start=end;
425 if (filename!=0) free(filename);
430 /************************** function suck_start ********************************
432 returns true if classbuffer is already loaded or a file for the
433 specified class has succussfully been read in. All directories of
434 the searchpath are used to find the classfile (<classname>.class).
435 Returns false if no classfile is found and writes an error message.
437 *******************************************************************************/
439 bool suck_start(utf *classname)
441 classpath_info *currPos;
444 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
450 if (classbuffer) return true; /* classbuffer is already valid */
452 utf_ptr = classname->text;
453 while (utf_ptr < utf_end(classname)) {
454 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
456 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
458 filename[filenamelen++] = c;
460 strcpy(filename + filenamelen, ".class");
462 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
464 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
465 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
466 unz_file_info file_info;
467 /*log_text("Class found in zip file");*/
468 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
469 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
470 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
471 classbuffer_size = file_info.uncompressed_size;
472 classbuffer = MNEW(u1, classbuffer_size);
473 classbuf_pos = classbuffer - 1;
474 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
475 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
476 unzCloseCurrentFile(currPos->archive.uf);
479 MFREE(classbuffer, u1, classbuffer_size);
480 log_text("Error while unzipping");
482 } else log_text("Error while opening file in archive");
483 } else log_text("Error while retrieving fileinfo");
485 unzCloseCurrentFile(currPos->archive.uf);
489 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
490 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
491 classfile = fopen(currPos->filepath.filename, "r");
492 if (classfile) { /* file exists */
494 /* determine size of classfile */
496 /* dolog("File: %s",filename); */
498 err = stat(currPos->filepath.filename, &buffer);
500 if (!err) { /* read classfile data */
501 classbuffer_size = buffer.st_size;
502 classbuffer = MNEW(u1, classbuffer_size);
503 classbuf_pos = classbuffer - 1;
504 fread(classbuffer, 1, classbuffer_size, classfile);
515 dolog("Warning: Can not open class file '%s'", filename);
522 /************************** function suck_stop *********************************
524 frees memory for buffer with classfile data.
525 Caution: this function may only be called if buffer has been allocated
526 by suck_start with reading a file
528 *******************************************************************************/
532 /* determine amount of classdata not retrieved by suck-operations */
534 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
536 if (classdata_left > 0) {
538 dolog("There are %d extra bytes at end of classfile",
540 /* The JVM spec disallows extra bytes. */
541 panic("Extra bytes at end of classfile");
546 MFREE(classbuffer, u1, classbuffer_size);
551 /******************************************************************************/
552 /******************* Some support functions ***********************************/
553 /******************************************************************************/
555 void fprintflags (FILE *fp, u2 f)
557 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
558 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
559 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
560 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
561 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
562 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
563 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
564 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
565 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
566 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
567 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
571 /********** internal function: printflags (only for debugging) ***************/
573 void printflags(u2 f)
575 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
576 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
577 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
578 if ( f & ACC_STATIC ) printf (" STATIC");
579 if ( f & ACC_FINAL ) printf (" FINAL");
580 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
581 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
582 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
583 if ( f & ACC_NATIVE ) printf (" NATIVE");
584 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
585 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
589 /************************* Function: skipattribute *****************************
591 skips a (1) 'attribute' structure in the class file
593 *******************************************************************************/
595 static void skipattribute()
604 /********************** Function: skipattributebody ****************************
606 skips an attribute after the 16 bit reference to attribute_name has already
609 *******************************************************************************/
611 static void skipattributebody()
619 /************************* Function: skipattributes ****************************
621 skips num attribute structures
623 *******************************************************************************/
625 static void skipattributes(u4 num)
628 for (i = 0; i < num; i++)
633 /******************** function: innerclass_getconstant ************************
635 like class_getconstant, but if cptags is ZERO null is returned
637 *******************************************************************************/
639 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
641 /* invalid position in constantpool */
642 if (pos >= c->cpcount)
643 panic("Attempt to access constant outside range");
645 /* constantpool entry of type 0 */
649 /* check type of constantpool entry */
650 if (c->cptags[pos] != ctype) {
651 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
652 (int) ctype, (int) c->cptags[pos] );
655 return c->cpinfos[pos];
659 /************************ function: attribute_load ****************************
661 read attributes from classfile
663 *******************************************************************************/
665 static void attribute_load(u4 num, classinfo *c)
669 for (i = 0; i < num; i++) {
670 /* retrieve attribute name */
671 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
673 if (aname == utf_innerclasses) {
674 /* innerclasses attribute */
676 if (c->innerclass != NULL)
677 panic("Class has more than one InnerClasses attribute");
679 /* skip attribute length */
681 /* number of records */
682 c->innerclasscount = suck_u2();
683 /* allocate memory for innerclass structure */
684 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
686 for (j = 0; j < c->innerclasscount; j++) {
687 /* The innerclass structure contains a class with an encoded name,
688 its defining scope, its simple name and a bitmask of the access flags.
689 If an inner class is not a member, its outer_class is NULL,
690 if a class is anonymous, its name is NULL. */
692 innerclassinfo *info = c->innerclass + j;
694 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
695 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
696 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
697 info->flags = suck_u2(); /* access_flags bitmask */
701 /* unknown attribute */
708 /******************* function: checkfielddescriptor ****************************
710 checks whether a field-descriptor is valid and aborts otherwise
711 all referenced classes are inserted into the list of unloaded classes
713 *******************************************************************************/
715 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
717 class_from_descriptor(utf_ptr,end_pos,NULL,
719 | CLASSLOAD_NULLPRIMITIVE
721 | CLASSLOAD_CHECKEND);
723 /* XXX use the following if -noverify */
725 char *tstart; /* pointer to start of classname */
727 char *start = utf_ptr;
729 switch (*utf_ptr++) {
743 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
744 panic ("Ill formed descriptor");
748 panic ("Ill formed descriptor");
751 /* exceeding characters */
752 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
757 /******************* function checkmethoddescriptor ****************************
759 checks whether a method-descriptor is valid and aborts otherwise.
760 All referenced classes are inserted into the list of unloaded classes.
762 The number of arguments is returned. A long or double argument is counted
765 *******************************************************************************/
767 static int checkmethoddescriptor (utf *d)
769 char *utf_ptr = d->text; /* current position in utf text */
770 char *end_pos = utf_end(d); /* points behind utf string */
771 int argcount = 0; /* number of arguments */
773 /* method descriptor must start with parenthesis */
774 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
776 /* check arguments */
777 while (utf_ptr != end_pos && *utf_ptr != ')') {
778 /* We cannot count the this argument here because
779 * we don't know if the method is static. */
780 if (*utf_ptr == 'J' || *utf_ptr == 'D')
784 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
786 | CLASSLOAD_NULLPRIMITIVE
790 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
791 utf_ptr++; /* skip ')' */
793 class_from_descriptor(utf_ptr,end_pos,NULL,
795 | CLASSLOAD_NULLPRIMITIVE
796 | CLASSLOAD_CHECKEND);
799 panic("Invalid method descriptor: too many arguments");
803 /* XXX use the following if -noverify */
805 /* check arguments */
806 while ((c = *utf_ptr++) != ')') {
823 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
824 panic ("Ill formed method descriptor");
828 panic ("Ill formed methodtype-descriptor");
832 /* check returntype */
834 /* returntype void */
835 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
838 /* treat as field-descriptor */
839 checkfielddescriptor (utf_ptr,end_pos);
844 /***************** Function: print_arraydescriptor ****************************
846 Debugging helper for displaying an arraydescriptor
848 *******************************************************************************/
850 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
853 fprintf(file, "<NULL>");
858 if (desc->componentvftbl) {
859 if (desc->componentvftbl->class)
860 utf_fprint(file, desc->componentvftbl->class->name);
862 fprintf(file, "<no classinfo>");
868 if (desc->elementvftbl) {
869 if (desc->elementvftbl->class)
870 utf_fprint(file, desc->elementvftbl->class->name);
872 fprintf(file, "<no classinfo>");
876 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
877 desc->dataoffset, desc->componentsize);
881 /******************************************************************************/
882 /************************** Functions for fields ****************************/
883 /******************************************************************************/
886 /************************ Function: field_load *********************************
888 Load everything about a class field from the class file and fill a
889 'fieldinfo' structure. For static fields, space in the data segment is
892 *******************************************************************************/
894 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
896 static void field_load(fieldinfo *f, classinfo *c)
900 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
902 f->flags = suck_u2(); /* ACC flags */
903 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
904 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
908 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
909 panic("Field with invalid name");
911 /* check flag consistency */
912 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
913 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
914 panic("Field has invalid access flags");
915 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
916 panic("Field is declared final and volatile");
917 if ((c->flags & ACC_INTERFACE) != 0) {
918 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
919 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
920 panic("Interface field is not declared static final public");
921 if ((f->flags & ACC_TRANSIENT) != 0)
922 panic("Interface field declared transient");
925 /* check descriptor */
926 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
929 f->type = jtype = desc_to_type(f->descriptor); /* data type */
930 f->offset = 0; /* offset from start of object */
935 case TYPE_INT: f->value.i = 0; break;
936 case TYPE_FLOAT: f->value.f = 0.0; break;
937 case TYPE_DOUBLE: f->value.d = 0.0; break;
938 case TYPE_ADDRESS: f->value.a = NULL; break;
941 f->value.l = 0; break;
943 f->value.l.low = 0; f->value.l.high = 0; break;
947 /* read attributes */
949 for (i = 0; i < attrnum; i++) {
952 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
954 if (aname != utf_constantvalue) {
955 /* unknown attribute */
959 /* constant value attribute */
961 if (pindex != field_load_NOVALUE)
962 panic("Field has more than one ConstantValue attribute");
964 /* check attribute length */
966 panic("ConstantValue attribute has invalid length");
968 /* index of value in constantpool */
971 /* initialize field with value from constantpool */
974 constant_integer *ci =
975 class_getconstant(c, pindex, CONSTANT_Integer);
976 f->value.i = ci->value;
982 class_getconstant(c, pindex, CONSTANT_Long);
983 f->value.l = cl->value;
989 class_getconstant(c, pindex, CONSTANT_Float);
990 f->value.f = cf->value;
995 constant_double *cd =
996 class_getconstant(c, pindex, CONSTANT_Double);
997 f->value.d = cd->value;
1001 case TYPE_ADDRESS: {
1002 utf *u = class_getconstant(c, pindex, CONSTANT_String);
1003 /* create javastring from compressed utf8-string */
1004 f->value.a = literalstring_new(u);
1009 log_text ("Invalid Constant - Type");
1016 /********************** function: field_free **********************************/
1018 static void field_free (fieldinfo *f)
1024 /**************** Function: field_display (debugging only) ********************/
1026 void field_display(fieldinfo *f)
1029 printflags(f->flags);
1031 utf_display(f->name);
1033 utf_display(f->descriptor);
1034 printf(" offset: %ld\n", (long int) (f->offset));
1038 /******************************************************************************/
1039 /************************* Functions for methods ******************************/
1040 /******************************************************************************/
1043 /*********************** Function: method_load *********************************
1045 Loads a method from the class file and fills an existing 'methodinfo'
1046 structure. For native methods, the function pointer field is set to the
1047 real function pointer, for JavaVM methods a pointer to the compiler is used
1050 *******************************************************************************/
1052 static void method_load(methodinfo *m, classinfo *c)
1058 count_all_methods++;
1060 m->thrownexceptionscount=0;
1061 m->linenumbercount=0;
1065 m->flags = suck_u2();
1066 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1069 if (!is_valid_name_utf(m->name))
1070 panic("Method with invalid name");
1071 if (m->name->text[0] == '<'
1072 && m->name != utf_init && m->name != utf_clinit)
1073 panic("Method with invalid special name");
1076 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1077 argcount = checkmethoddescriptor(m->descriptor);
1078 if ((m->flags & ACC_STATIC) == 0)
1079 argcount++; /* count the 'this' argument */
1083 panic("Method has more than 255 arguments");
1085 /* check flag consistency */
1086 if (m->name != utf_clinit) {
1087 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1088 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1089 panic("Method has invalid access flags");
1090 if ((m->flags & ACC_ABSTRACT) != 0) {
1091 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1092 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1093 panic("Abstract method has invalid flags set");
1095 if ((c->flags & ACC_INTERFACE) != 0) {
1096 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1097 != (ACC_ABSTRACT | ACC_PUBLIC))
1098 panic("Interface method is not declared abstract and public");
1100 if (m->name == utf_init) {
1101 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1102 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1103 panic("Instance initialization method has invalid flags set");
1109 m->exceptiontable = NULL;
1110 m->entrypoint = NULL;
1112 m->stubroutine = NULL;
1113 m->methodUsed = NOTUSED;
1116 m->subRedefsUsed = 0;
1120 if (!(m->flags & ACC_NATIVE)) {
1121 m->stubroutine = createcompilerstub(m);
1124 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1125 (m->flags & ACC_STATIC) != 0);
1127 m->stubroutine = createnativestub(f, m);
1132 attrnum = suck_u2();
1133 for (i = 0; i < attrnum; i++) {
1136 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1138 if (aname != utf_code) {
1139 if (aname == utf_exceptions) {
1142 suck_u4(); /*length*/
1143 exceptionCount=suck_u2();
1144 m->thrownexceptionscount=exceptionCount;
1145 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1146 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1147 (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(),CONSTANT_Class);
1151 skipattributebody();
1155 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1156 panic("Code attribute for native or abstract method");
1159 panic("Method has more than one Code attribute");
1162 m->maxstack = suck_u2();
1163 m->maxlocals = suck_u2();
1164 if (m->maxlocals < argcount)
1165 panic("max_locals is smaller than the number of arguments");
1167 codelen = suck_u4();
1169 panic("bytecode has zero length");
1170 if (codelen > 65536)
1171 panic("bytecode too long");
1172 m->jcodelength = codelen;
1173 m->jcode = MNEW(u1, m->jcodelength);
1174 suck_nbytes(m->jcode, m->jcodelength);
1175 m->exceptiontablelength = suck_u2();
1177 MNEW(exceptiontable, m->exceptiontablelength);
1180 count_vmcode_len += m->jcodelength + 18;
1181 count_extable_len += 8 * m->exceptiontablelength;
1184 for (e = 0; e < m->exceptiontablelength; e++) {
1186 m->exceptiontable[e].startpc = suck_u2();
1187 m->exceptiontable[e].endpc = suck_u2();
1188 m->exceptiontable[e].handlerpc = suck_u2();
1192 m->exceptiontable[e].catchtype = NULL;
1195 m->exceptiontable[e].catchtype =
1196 class_getconstant(c, idx, CONSTANT_Class);
1201 for (codeattrnum=suck_u2();codeattrnum>0;codeattrnum--) {
1202 utf * caname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1203 if (caname==utf_linenumbertable) {
1205 /*log_text("LineNumberTable found");*/
1207 m->linenumbercount=suck_u2();
1208 /*printf("length:%d\n",m->linenumbercount);*/
1209 m->linenumbers=MNEW(lineinfo,m->linenumbercount);
1210 for (lncid=0;lncid<m->linenumbercount;lncid++) {
1211 m->linenumbers[lncid].start_pc=suck_u2();
1212 m->linenumbers[lncid].line_number=suck_u2();
1215 skipattributes(codeattrnum);
1217 } else skipattributebody();
1224 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1225 panic("Method missing Code attribute");
1229 /********************* Function: method_free ***********************************
1231 frees all memory that was allocated for this method
1233 *******************************************************************************/
1235 static void method_free(methodinfo *m)
1238 MFREE(m->jcode, u1, m->jcodelength);
1240 if (m->exceptiontable)
1241 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1244 CFREE(m->mcode, m->mcodelength);
1246 if (m->stubroutine) {
1247 if (m->flags & ACC_NATIVE) {
1248 removenativestub(m->stubroutine);
1251 removecompilerstub(m->stubroutine);
1257 /************** Function: method_display (debugging only) **************/
1259 void method_display(methodinfo *m)
1262 printflags(m->flags);
1264 utf_display(m->name);
1266 utf_display(m->descriptor);
1270 /************** Function: method_display_flags_last (debugging only) **************/
1272 void method_display_flags_last(methodinfo *m)
1275 utf_display(m->name);
1277 utf_display(m->descriptor);
1279 printflags(m->flags);
1284 /******************** Function: method_canoverwrite ****************************
1286 Check if m and old are identical with respect to type and name. This means
1287 that old can be overwritten with m.
1289 *******************************************************************************/
1291 static bool method_canoverwrite(methodinfo *m, methodinfo *old)
1293 if (m->name != old->name) return false;
1294 if (m->descriptor != old->descriptor) return false;
1295 if (m->flags & ACC_STATIC) return false;
1302 /******************************************************************************/
1303 /************************ Functions for class *********************************/
1304 /******************************************************************************/
1307 /******************** function:: class_getconstant ******************************
1309 retrieves the value at position 'pos' of the constantpool of a class
1310 if the type of the value is other than 'ctype' the system is stopped
1312 *******************************************************************************/
1314 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1316 /* invalid position in constantpool */
1317 /* (pos == 0 is caught by type comparison) */
1318 if (pos >= c->cpcount)
1319 panic("Attempt to access constant outside range");
1321 /* check type of constantpool entry */
1323 if (c->cptags[pos] != ctype) {
1324 class_showconstantpool(c);
1325 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1326 (int) ctype, (int) c->cptags[pos]);
1329 return c->cpinfos[pos];
1333 /********************* Function: class_constanttype ****************************
1335 Determines the type of a class entry in the ConstantPool
1337 *******************************************************************************/
1339 u4 class_constanttype(classinfo *c, u4 pos)
1341 if (pos >= c->cpcount)
1342 panic("Attempt to access constant outside range");
1344 return c->cptags[pos];
1348 /******************** function: class_loadcpool ********************************
1350 loads the constantpool of a class,
1351 the entries are transformed into a simpler format
1352 by resolving references
1353 (a detailed overview of the compact structures can be found in global.h)
1355 *******************************************************************************/
1357 static void class_loadcpool(classinfo *c)
1360 /* The following structures are used to save information which cannot be
1361 processed during the first pass. After the complete constantpool has
1362 been traversed the references can be resolved.
1363 (only in specific order) */
1365 /* CONSTANT_Class_info entries */
1366 typedef struct forward_class {
1367 struct forward_class *next;
1372 /* CONSTANT_String */
1373 typedef struct forward_string {
1374 struct forward_string *next;
1379 /* CONSTANT_NameAndType */
1380 typedef struct forward_nameandtype {
1381 struct forward_nameandtype *next;
1385 } forward_nameandtype;
1387 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1388 typedef struct forward_fieldmethint {
1389 struct forward_fieldmethint *next;
1393 u2 nameandtype_index;
1394 } forward_fieldmethint;
1398 long int dumpsize = dump_size ();
1400 forward_class *forward_classes = NULL;
1401 forward_string *forward_strings = NULL;
1402 forward_nameandtype *forward_nameandtypes = NULL;
1403 forward_fieldmethint *forward_fieldmethints = NULL;
1405 /* number of entries in the constant_pool table plus one */
1406 u4 cpcount = c->cpcount = suck_u2();
1408 /* allocate memory */
1409 u1 *cptags = c->cptags = MNEW(u1, cpcount);
1410 voidptr *cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1413 panic("Invalid constant_pool_count (0)");
1416 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1419 /* initialize constantpool */
1420 for (idx = 0; idx < cpcount; idx++) {
1421 cptags[idx] = CONSTANT_UNUSED;
1422 cpinfos[idx] = NULL;
1426 /******* first pass *******/
1427 /* entries which cannot be resolved now are written into
1428 temporary structures and traversed again later */
1431 while (idx < cpcount) {
1432 /* get constant type */
1436 case CONSTANT_Class: {
1437 forward_class *nfc = DNEW(forward_class);
1439 nfc -> next = forward_classes;
1440 forward_classes = nfc;
1442 nfc -> thisindex = idx;
1443 /* reference to CONSTANT_NameAndType */
1444 nfc -> name_index = suck_u2 ();
1450 case CONSTANT_Fieldref:
1451 case CONSTANT_Methodref:
1452 case CONSTANT_InterfaceMethodref: {
1453 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1455 nff -> next = forward_fieldmethints;
1456 forward_fieldmethints = nff;
1458 nff -> thisindex = idx;
1461 /* class or interface type that contains the declaration of the field or method */
1462 nff -> class_index = suck_u2 ();
1463 /* name and descriptor of the field or method */
1464 nff -> nameandtype_index = suck_u2 ();
1470 case CONSTANT_String: {
1471 forward_string *nfs = DNEW(forward_string);
1473 nfs->next = forward_strings;
1474 forward_strings = nfs;
1476 nfs->thisindex = idx;
1477 /* reference to CONSTANT_Utf8_info with string characters */
1478 nfs->string_index = suck_u2();
1484 case CONSTANT_NameAndType: {
1485 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1487 nfn -> next = forward_nameandtypes;
1488 forward_nameandtypes = nfn;
1490 nfn -> thisindex = idx;
1491 /* reference to CONSTANT_Utf8_info containing simple name */
1492 nfn -> name_index = suck_u2 ();
1493 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1494 nfn -> sig_index = suck_u2 ();
1500 case CONSTANT_Integer: {
1501 constant_integer *ci = NEW (constant_integer);
1504 count_const_pool_len += sizeof(constant_integer);
1507 ci -> value = suck_s4 ();
1508 cptags [idx] = CONSTANT_Integer;
1515 case CONSTANT_Float: {
1516 constant_float *cf = NEW (constant_float);
1519 count_const_pool_len += sizeof(constant_float);
1522 cf -> value = suck_float ();
1523 cptags [idx] = CONSTANT_Float;
1529 case CONSTANT_Long: {
1530 constant_long *cl = NEW(constant_long);
1533 count_const_pool_len += sizeof(constant_long);
1536 cl -> value = suck_s8 ();
1537 cptags [idx] = CONSTANT_Long;
1541 panic("Long constant exceeds constant pool");
1545 case CONSTANT_Double: {
1546 constant_double *cd = NEW(constant_double);
1549 count_const_pool_len += sizeof(constant_double);
1552 cd -> value = suck_double ();
1553 cptags [idx] = CONSTANT_Double;
1557 panic("Double constant exceeds constant pool");
1561 case CONSTANT_Utf8: {
1563 /* number of bytes in the bytes array (not string-length) */
1564 u4 length = suck_u2();
1565 cptags [idx] = CONSTANT_Utf8;
1566 /* validate the string */
1567 ASSERT_LEFT(length);
1569 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1571 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1572 panic("Invalid UTF-8 string");
1574 /* insert utf-string into the utf-symboltable */
1575 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1576 /* skip bytes of the string */
1577 skip_nbytes(length);
1583 error ("Unkown constant type: %d",(int) t);
1591 /* resolve entries in temporary structures */
1593 while (forward_classes) {
1595 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1597 if (opt_verify && !is_valid_name_utf(name))
1598 panic("Class reference with invalid name");
1600 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1601 /* retrieve class from class-table */
1602 cpinfos [forward_classes -> thisindex] = class_new (name);
1604 forward_classes = forward_classes -> next;
1608 while (forward_strings) {
1610 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1612 log_text("forward_string:");
1613 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1615 log_text("\n------------------"); */
1616 /* resolve utf-string */
1617 cptags [forward_strings -> thisindex] = CONSTANT_String;
1618 cpinfos [forward_strings -> thisindex] = text;
1620 forward_strings = forward_strings -> next;
1623 while (forward_nameandtypes) {
1624 constant_nameandtype *cn = NEW (constant_nameandtype);
1627 count_const_pool_len += sizeof(constant_nameandtype);
1630 /* resolve simple name and descriptor */
1631 cn -> name = class_getconstant
1632 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1633 cn -> descriptor = class_getconstant
1634 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1638 if (!is_valid_name_utf(cn->name))
1639 panic("NameAndType with invalid name");
1640 /* disallow referencing <clinit> among others */
1641 if (cn->name->text[0] == '<' && cn->name != utf_init)
1642 panic("NameAndType with invalid special name");
1645 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1646 cpinfos [forward_nameandtypes -> thisindex] = cn;
1648 forward_nameandtypes = forward_nameandtypes -> next;
1652 while (forward_fieldmethints) {
1653 constant_nameandtype *nat;
1654 constant_FMIref *fmi = NEW (constant_FMIref);
1657 count_const_pool_len += sizeof(constant_FMIref);
1659 /* resolve simple name and descriptor */
1660 nat = class_getconstant
1661 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1664 log_text("trying to resolve:");
1665 log_text(nat->name->text);
1666 switch(forward_fieldmethints ->tag) {
1667 case CONSTANT_Fieldref:
1668 log_text("CONSTANT_Fieldref");
1670 case CONSTANT_InterfaceMethodref:
1671 log_text("CONSTANT_InterfaceMethodref");
1673 case CONSTANT_Methodref:
1674 log_text("CONSTANT_Methodref");
1678 fmi -> class = class_getconstant
1679 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1680 fmi -> name = nat -> name;
1681 fmi -> descriptor = nat -> descriptor;
1683 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1684 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1686 switch (forward_fieldmethints -> tag) {
1687 case CONSTANT_Fieldref: /* check validity of descriptor */
1688 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1690 case CONSTANT_InterfaceMethodref:
1691 case CONSTANT_Methodref: /* check validity of descriptor */
1692 checkmethoddescriptor (fmi->descriptor);
1696 forward_fieldmethints = forward_fieldmethints -> next;
1700 /* class_showconstantpool(c); */
1702 dump_release(dumpsize);
1706 /********************** Function: class_load ***********************************
1708 Loads everything interesting about a class from the class file. The
1709 'classinfo' structure must have been allocated previously.
1711 The super class and the interfaces implemented by this class need not be
1712 loaded. The link is set later by the function 'class_link'.
1714 The loaded class is removed from the list 'unloadedclasses' and added to
1715 the list 'unlinkedclasses'.
1717 *******************************************************************************/
1719 static int class_load(classinfo *c)
1725 count_class_loads++;
1728 /* output for debugging purposes */
1730 char logtext[MAXLOGTEXT];
1731 sprintf(logtext, "Loading class: ");
1732 utf_sprint(logtext + strlen(logtext), c->name);
1736 /* load classdata, throw exception on error */
1738 if (!suck_start(c->name)) {
1739 throw_noclassdeffounderror_message(c->name);
1743 /* check signature */
1744 if (suck_u4() != MAGIC)
1745 panic("Can not find class-file signature");
1750 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1751 error("File version %d.%d is not supported", (int) ma, (int) mi);
1756 c->erroneous_state = 0;
1757 c->initializing_thread = 0;
1759 c->classUsed = NOTUSED; /* not used initially CO-RT */
1763 c->flags = suck_u2();
1764 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1766 /* check ACC flags consistency */
1767 if ((c->flags & ACC_INTERFACE) != 0) {
1768 if ((c->flags & ACC_ABSTRACT) == 0) {
1769 /* We work around this because interfaces in JDK 1.1 are
1770 * not declared abstract. */
1772 c->flags |= ACC_ABSTRACT;
1773 /* panic("Interface class not declared abstract"); */
1775 if ((c->flags & (ACC_FINAL)) != 0)
1776 panic("Interface class has invalid flags");
1777 if ((c->flags & (ACC_SUPER)) != 0)
1778 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1780 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1781 panic("Class is declared both abstract and final");
1785 if (class_getconstant(c, i, CONSTANT_Class) != c) {
1786 /* char message[MAXLOGTEXT]; */
1787 /* utf_sprint(message, c->name); */
1788 /* sprintf(message + strlen(message), " (wrong name: "); */
1789 /* utf_sprint(message + strlen(message), class_getconstant(c, i, CONSTANT_Class)); */
1790 /* sprintf(message + strlen(message), ")"); */
1792 /* *exceptionptr = new_exception_message("java/lang/NoClassDefFoundError", */
1795 panic("Invalid this_class in class file");
1798 /* retrieve superclass */
1799 if ((i = suck_u2())) {
1800 c->super = class_getconstant(c, i, CONSTANT_Class);
1802 /* java.lang.Object may not have a super class. */
1803 if (c->name == utf_java_lang_Object)
1804 panic("java.lang.Object with super class");
1806 /* Interfaces must have j.l.O as super class. */
1807 if ((c->flags & ACC_INTERFACE) != 0
1808 && c->super->name != utf_java_lang_Object)
1810 panic("Interface with super class other than java.lang.Object");
1815 /* This is only allowed for java.lang.Object. */
1816 if (c->name != utf_java_lang_Object)
1817 panic("Class (not java.lang.Object) without super class");
1820 /* retrieve interfaces */
1821 c->interfacescount = suck_u2();
1822 c->interfaces = MNEW(classinfo*, c->interfacescount);
1823 for (i = 0; i < c->interfacescount; i++) {
1825 class_getconstant(c, suck_u2(), CONSTANT_Class);
1829 c->fieldscount = suck_u2();
1830 /* utf_display(c->name);
1831 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1833 c->fields = GCNEW(fieldinfo, c->fieldscount);
1834 for (i = 0; i < c->fieldscount; i++) {
1835 field_load(&(c->fields[i]), c);
1839 c->methodscount = suck_u2();
1840 c->methods = MNEW(methodinfo, c->methodscount);
1841 for (i = 0; i < c->methodscount; i++) {
1842 method_load(&(c->methods[i]), c);
1845 /* Check if all fields and methods can be uniquely
1846 * identified by (name,descriptor). */
1848 /* We use a hash table here to avoid making the
1849 * average case quadratic in # of methods, fields.
1851 static int shift = 0;
1853 u2 *next; /* for chaining colliding hash entries */
1859 /* Allocate hashtable */
1860 len = c->methodscount;
1861 if (len < c->fieldscount) len = c->fieldscount;
1863 hashtab = MNEW(u2,(hashlen + len));
1864 next = hashtab + hashlen;
1866 /* Determine bitshift (to get good hash values) */
1876 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
1877 for (i = 0; i < c->fieldscount; ++i) {
1878 fieldinfo *fi = c->fields + i;
1879 /* It's ok if we lose bits here */
1880 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1882 if ((old = hashtab[index]) != 0) {
1884 /* dolog("HASHHIT %d --> %d",index,old); */
1887 /* dolog("HASHCHECK %d",old); */
1888 if (c->fields[old].name == fi->name
1889 && c->fields[old].descriptor == fi->descriptor)
1891 dolog("Duplicate field (%d,%d):",i,old);
1892 log_utf(fi->name); log_utf(fi->descriptor);
1893 panic("Fields with same name and descriptor");
1895 } while ((old = next[old]) != 0);
1897 /* else dolog("HASHLUCKY"); */
1898 hashtab[index] = i+1;
1902 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1903 for (i = 0; i < c->methodscount; ++i) {
1904 methodinfo *mi = c->methods + i;
1905 /* It's ok if we lose bits here */
1906 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1908 if ((old = hashtab[index]) != 0) {
1910 /* dolog("HASHHIT %d --> %d",index,old); */
1913 /* dolog("HASHCHECK %d",old); */
1914 if (c->methods[old].name == mi->name
1915 && c->methods[old].descriptor == mi->descriptor)
1917 dolog("Duplicate method (%d,%d):",i,old);
1918 log_utf(mi->name); log_utf(mi->descriptor);
1919 panic("Methods with same name and descriptor");
1921 } while ((old = next[old]) != 0);
1923 /* else dolog("HASHLUCKY"); */
1924 hashtab[index] = i+1;
1927 MFREE(hashtab,u2,(hashlen + len));
1931 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1932 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1933 count_class_infos += sizeof(methodinfo) * c->methodscount;
1936 /* load variable-length attribute structures */
1937 attribute_load(suck_u2(), c);
1942 /* remove class from list of unloaded classes and
1943 add to list of unlinked classes */
1944 list_remove(&unloadedclasses, c);
1945 list_addlast(&unlinkedclasses, c);
1954 /************** internal Function: class_highestinterface ***********************
1956 Used by the function class_link to determine the amount of memory needed
1957 for the interface table.
1959 *******************************************************************************/
1961 static s4 class_highestinterface(classinfo *c)
1966 if (!(c->flags & ACC_INTERFACE)) {
1967 char logtext[MAXLOGTEXT];
1968 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1969 utf_sprint(logtext + strlen(logtext), c->name);
1970 error("%s",logtext);
1974 for (i = 0; i < c->interfacescount; i++) {
1975 s4 h2 = class_highestinterface(c->interfaces[i]);
1983 /* class_addinterface **********************************************************
1985 Is needed by class_link for adding a VTBL to a class. All interfaces
1986 implemented by ic are added as well.
1988 *******************************************************************************/
1990 static void class_addinterface (classinfo *c, classinfo *ic)
1994 vftbl *vftbl = c->vftbl;
1996 if (i >= vftbl->interfacetablelength)
1997 panic ("Inernal error: interfacetable overflow");
1998 if (vftbl->interfacetable[-i])
2001 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
2002 vftbl->interfacevftbllength[i] = 1;
2003 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
2004 vftbl->interfacetable[-i][0] = NULL;
2007 vftbl->interfacevftbllength[i] = ic->methodscount;
2008 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
2011 count_vftbl_len += sizeof(methodptr) *
2012 (ic->methodscount + (ic->methodscount == 0));
2015 for (j=0; j<ic->methodscount; j++) {
2018 for (m = 0; m < sc->methodscount; m++) {
2019 methodinfo *mi = &(sc->methods[m]);
2020 if (method_canoverwrite(mi, &(ic->methods[j]))) {
2021 vftbl->interfacetable[-i][j] =
2022 vftbl->table[mi->vftblindex];
2032 for (j = 0; j < ic->interfacescount; j++)
2033 class_addinterface(c, ic->interfaces[j]);
2037 /******************* Function: class_new_array *********************************
2039 This function is called by class_new to setup an array class.
2041 *******************************************************************************/
2043 void class_new_array(classinfo *c)
2045 classinfo *comp = NULL;
2049 /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
2051 /* Array classes are not loaded from classfiles. */
2052 list_remove(&unloadedclasses, c);
2054 /* Check array class name */
2055 namelen = c->name->blength;
2056 if (namelen < 2 || c->name->text[0] != '[')
2057 panic("Invalid array class name");
2059 /* Check the component type */
2060 switch (c->name->text[1]) {
2062 /* c is an array of arrays. We have to create the component class. */
2063 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
2067 /* c is an array of objects. */
2068 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2069 panic("Invalid array class name");
2070 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2074 /* Setup the array class */
2075 c->super = class_java_lang_Object;
2076 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2078 c->interfacescount = 2;
2079 c->interfaces = MNEW(classinfo*,2);
2080 c->interfaces[0] = class_java_lang_Cloneable;
2081 c->interfaces[1] = class_java_io_Serializable;
2083 c->methodscount = 1;
2084 c->methods = MNEW (methodinfo, c->methodscount);
2087 memset(clone, 0, sizeof(methodinfo));
2088 clone->flags = ACC_PUBLIC;
2089 clone->name = utf_new_char("clone");
2090 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2092 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2093 clone->monoPoly = MONO;
2095 /* XXX: field: length? */
2097 /* The array class has to be linked */
2098 list_addlast(&unlinkedclasses,c);
2101 * Array classes which are created after the other classes have been
2102 * loaded and linked are linked explicitely.
2107 loader_load(c->name); /* XXX handle errors */
2111 /****************** Function: class_link_array *********************************
2113 This function is called by class_link to create the
2114 arraydescriptor for an array class.
2116 This function returns NULL if the array cannot be linked because
2117 the component type has not been linked yet.
2119 *******************************************************************************/
2121 static arraydescriptor *class_link_array(classinfo *c)
2123 classinfo *comp = NULL;
2124 int namelen = c->name->blength;
2125 arraydescriptor *desc;
2128 /* Check the component type */
2129 switch (c->name->text[1]) {
2131 /* c is an array of arrays. */
2132 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2133 if (!comp) panic("Could not find component array class.");
2137 /* c is an array of objects. */
2138 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2139 if (!comp) panic("Could not find component class.");
2143 /* If the component type has not been linked return NULL */
2144 if (comp && !comp->linked)
2147 /* Allocate the arraydescriptor */
2148 desc = NEW(arraydescriptor);
2151 /* c is an array of references */
2152 desc->arraytype = ARRAYTYPE_OBJECT;
2153 desc->componentsize = sizeof(void*);
2154 desc->dataoffset = OFFSET(java_objectarray,data);
2156 compvftbl = comp->vftbl;
2158 panic("Component class has no vftbl");
2159 desc->componentvftbl = compvftbl;
2161 if (compvftbl->arraydesc) {
2162 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2163 if (compvftbl->arraydesc->dimension >= 255)
2164 panic("Creating array of dimension >255");
2165 desc->dimension = compvftbl->arraydesc->dimension + 1;
2166 desc->elementtype = compvftbl->arraydesc->elementtype;
2169 desc->elementvftbl = compvftbl;
2170 desc->dimension = 1;
2171 desc->elementtype = ARRAYTYPE_OBJECT;
2175 /* c is an array of a primitive type */
2176 switch (c->name->text[1]) {
2177 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2178 desc->dataoffset = OFFSET(java_booleanarray,data);
2179 desc->componentsize = sizeof(u1);
2182 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2183 desc->dataoffset = OFFSET(java_bytearray,data);
2184 desc->componentsize = sizeof(u1);
2187 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2188 desc->dataoffset = OFFSET(java_chararray,data);
2189 desc->componentsize = sizeof(u2);
2192 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2193 desc->dataoffset = OFFSET(java_doublearray,data);
2194 desc->componentsize = sizeof(double);
2197 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2198 desc->dataoffset = OFFSET(java_floatarray,data);
2199 desc->componentsize = sizeof(float);
2202 case 'I': desc->arraytype = ARRAYTYPE_INT;
2203 desc->dataoffset = OFFSET(java_intarray,data);
2204 desc->componentsize = sizeof(s4);
2207 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2208 desc->dataoffset = OFFSET(java_longarray,data);
2209 desc->componentsize = sizeof(s8);
2212 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2213 desc->dataoffset = OFFSET(java_shortarray,data);
2214 desc->componentsize = sizeof(s2);
2218 panic("Invalid array class name");
2221 desc->componentvftbl = NULL;
2222 desc->elementvftbl = NULL;
2223 desc->dimension = 1;
2224 desc->elementtype = desc->arraytype;
2231 /********************** Function: class_link ***********************************
2233 Tries to link a class. The super class and every implemented interface must
2234 already have been linked. The function calculates the length in bytes that
2235 an instance of this class requires as well as the VTBL for methods and
2238 If the class can be linked, it is removed from the list 'unlinkedclasses'
2239 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2242 Attention: If cyclical class definitions are encountered, the program gets
2243 into an infinite loop (we'll have to work that out)
2245 *******************************************************************************/
2247 void class_link(classinfo *c)
2249 s4 supervftbllength; /* vftbllegnth of super class */
2250 s4 vftbllength; /* vftbllength of current class */
2251 s4 interfacetablelength; /* interface table length */
2252 classinfo *super = c->super; /* super class */
2253 classinfo *ic, *c2; /* intermediate class variables */
2254 vftbl *v; /* vftbl of current class */
2255 s4 i; /* interface/method/field counter */
2256 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2259 /* check if all superclasses are already linked, if not put c at end of
2260 unlinked list and return. Additionally initialize class fields. */
2262 /* check interfaces */
2264 for (i = 0; i < c->interfacescount; i++) {
2265 ic = c->interfaces[i];
2267 list_remove(&unlinkedclasses, c);
2268 list_addlast(&unlinkedclasses, c);
2271 if ((ic->flags & ACC_INTERFACE) == 0) {
2272 dolog("Specified interface is not declared as interface:");
2276 panic("Specified interface is not declared as interface");
2280 /* check super class */
2282 if (super == NULL) { /* class java.long.Object */
2284 c->classUsed = USED; /* Object class is always used CO-RT*/
2286 c->instancesize = sizeof(java_objectheader);
2288 vftbllength = supervftbllength = 0;
2290 c->finalizer = NULL;
2293 if (!super->linked) {
2294 list_remove(&unlinkedclasses, c);
2295 list_addlast(&unlinkedclasses, c);
2299 if (super->flags & ACC_INTERFACE)
2300 panic("Interface specified as super class");
2302 /* handle array classes */
2303 /* The component class must have been linked already. */
2304 if (c->name->text[0] == '[')
2305 if ((arraydesc = class_link_array(c)) == NULL) {
2306 list_remove(&unlinkedclasses, c);
2307 list_addlast(&unlinkedclasses, c);
2311 /* Don't allow extending final classes */
2312 if (super->flags & ACC_FINAL)
2313 panic("Trying to extend final class");
2315 if (c->flags & ACC_INTERFACE)
2316 c->index = interfaceindex++;
2318 c->index = super->index + 1;
2320 c->instancesize = super->instancesize;
2322 vftbllength = supervftbllength = super->vftbl->vftbllength;
2324 c->finalizer = super->finalizer;
2329 char logtext[MAXLOGTEXT];
2330 sprintf(logtext, "Linking Class: ");
2331 utf_sprint(logtext + strlen(logtext), c->name );
2335 /* compute vftbl length */
2337 for (i = 0; i < c->methodscount; i++) {
2338 methodinfo *m = &(c->methods[i]);
2340 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2341 classinfo *sc = super;
2344 for (j = 0; j < sc->methodscount; j++) {
2345 if (method_canoverwrite(m, &(sc->methods[j]))) {
2346 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2347 goto notfoundvftblindex;
2348 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2351 log_utf(sc->methods[j].name);
2352 log_utf(sc->methods[j].descriptor);
2353 panic("Trying to overwrite final method");
2355 m->vftblindex = sc->methods[j].vftblindex;
2356 goto foundvftblindex;
2362 m->vftblindex = (vftbllength++);
2368 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2371 /* compute interfacetable length */
2373 interfacetablelength = 0;
2376 for (i = 0; i < c2->interfacescount; i++) {
2377 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2378 if (h > interfacetablelength)
2379 interfacetablelength = h;
2384 /* allocate virtual function table */
2386 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2387 (vftbllength - 1) + sizeof(methodptr*) *
2388 (interfacetablelength - (interfacetablelength > 0)));
2389 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2390 (interfacetablelength > 1));
2391 c->header.vftbl = c->vftbl = v;
2393 v->vftbllength = vftbllength;
2394 v->interfacetablelength = interfacetablelength;
2395 v->arraydesc = arraydesc;
2397 /* store interface index in vftbl */
2398 if (c->flags & ACC_INTERFACE)
2399 v->baseval = -(c->index);
2401 /* copy virtual function table of super class */
2403 for (i = 0; i < supervftbllength; i++)
2404 v->table[i] = super->vftbl->table[i];
2406 /* add method stubs into virtual function table */
2408 for (i = 0; i < c->methodscount; i++) {
2409 methodinfo *m = &(c->methods[i]);
2410 if (!(m->flags & ACC_STATIC)) {
2411 v->table[m->vftblindex] = m->stubroutine;
2415 /* compute instance size and offset of each field */
2417 for (i = 0; i < c->fieldscount; i++) {
2419 fieldinfo *f = &(c->fields[i]);
2421 if (!(f->flags & ACC_STATIC) ) {
2422 dsize = desc_typesize(f->descriptor);
2423 c->instancesize = ALIGN(c->instancesize, dsize);
2424 f->offset = c->instancesize;
2425 c->instancesize += dsize;
2429 /* initialize interfacetable and interfacevftbllength */
2431 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2434 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2437 for (i = 0; i < interfacetablelength; i++) {
2438 v->interfacevftbllength[i] = 0;
2439 v->interfacetable[-i] = NULL;
2442 /* add interfaces */
2444 for (c2 = c; c2 != NULL; c2 = c2->super)
2445 for (i = 0; i < c2->interfacescount; i++) {
2446 class_addinterface(c, c2->interfaces[i]);
2449 /* add finalizer method (not for java.lang.Object) */
2451 if (super != NULL) {
2453 static utf *finame = NULL;
2454 static utf *fidesc = NULL;
2457 finame = utf_finalize;
2459 fidesc = utf_fidesc;
2461 fi = class_findmethod(c, finame, fidesc);
2463 if (!(fi->flags & ACC_STATIC)) {
2473 list_remove(&unlinkedclasses, c);
2474 list_addlast(&linkedclasses, c);
2478 /******************* Function: class_freepool **********************************
2480 Frees all resources used by this classes Constant Pool.
2482 *******************************************************************************/
2484 static void class_freecpool (classinfo *c)
2490 for (idx=0; idx < c->cpcount; idx++) {
2491 tag = c->cptags[idx];
2492 info = c->cpinfos[idx];
2496 case CONSTANT_Fieldref:
2497 case CONSTANT_Methodref:
2498 case CONSTANT_InterfaceMethodref:
2499 FREE (info, constant_FMIref);
2501 case CONSTANT_Integer:
2502 FREE (info, constant_integer);
2504 case CONSTANT_Float:
2505 FREE (info, constant_float);
2508 FREE (info, constant_long);
2510 case CONSTANT_Double:
2511 FREE (info, constant_double);
2513 case CONSTANT_NameAndType:
2514 FREE (info, constant_nameandtype);
2520 MFREE (c -> cptags, u1, c -> cpcount);
2521 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2525 /*********************** Function: class_free **********************************
2527 Frees all resources used by the class.
2529 *******************************************************************************/
2531 static void class_free(classinfo *c)
2538 MFREE(c->interfaces, classinfo*, c->interfacescount);
2540 for (i = 0; i < c->fieldscount; i++)
2541 field_free(&(c->fields[i]));
2543 for (i = 0; i < c->methodscount; i++)
2544 method_free(&(c->methods[i]));
2545 MFREE(c->methods, methodinfo, c->methodscount);
2547 if ((v = c->vftbl) != NULL) {
2549 mem_free(v->arraydesc,sizeof(arraydescriptor));
2551 for (i = 0; i < v->interfacetablelength; i++) {
2552 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2554 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2556 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2557 sizeof(methodptr*) * (v->interfacetablelength -
2558 (v->interfacetablelength > 0));
2559 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2560 (v->interfacetablelength > 1));
2564 if (c->innerclasscount)
2565 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2567 /* if (c->classvftbl)
2568 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2574 /************************* Function: class_findfield ***************************
2576 Searches a 'classinfo' structure for a field having the given name and
2579 *******************************************************************************/
2581 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2585 for (i = 0; i < c->fieldscount; i++) {
2586 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2587 return &(c->fields[i]);
2590 panic("Can not find field given in CONSTANT_Fieldref");
2592 /* keep compiler happy */
2597 /************************* Function: class_findmethod **************************
2599 Searches a 'classinfo' structure for a method having the given name and
2600 type and returns the index in the class info structure.
2601 If type is NULL, it is ignored.
2603 *******************************************************************************/
2605 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2608 //#define JOWENN_DEBUG1
2609 //#define JOWENN_DEBUG2
2610 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2612 int buffer_len, pos;
2615 #ifdef JOWENN_DEBUG1
2618 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2620 buffer = MNEW(char, buffer_len);
2622 strcpy(buffer, "class_findmethod: method:");
2623 utf_sprint(buffer + strlen(buffer), name);
2624 strcpy(buffer + strlen(buffer), ", desc: ");
2625 utf_sprint(buffer + strlen(buffer), desc);
2626 strcpy(buffer + strlen(buffer), ", classname: ");
2627 utf_sprint(buffer + strlen(buffer), c->name);
2631 MFREE(buffer, char, buffer_len);
2633 for (i = 0; i < c->methodscount; i++) {
2634 #ifdef JOWENN_DEBUG2
2636 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2638 buffer = MNEW(char, buffer_len);
2640 strcpy(buffer, "class_findmethod: comparing to method:");
2641 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2642 strcpy(buffer + strlen(buffer), ", desc: ");
2643 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2647 MFREE(buffer, char, buffer_len);
2651 if ((c->methods[i].name == name) && ((desc == NULL) ||
2652 (c->methods[i].descriptor == desc))) {
2657 #ifdef JOWENN_DEBUG2
2658 class_showconstantpool(c);
2659 log_text("class_findmethod: returning NULL");
2666 /************************* Function: class_findmethod **************************
2668 Searches a 'classinfo' structure for a method having the given name and
2670 If type is NULL, it is ignored.
2672 *******************************************************************************/
2674 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2678 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2680 int buffer_len, pos;
2682 #ifdef JOWENN_DEBUG1
2685 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2687 buffer = MNEW(char, buffer_len);
2689 strcpy(buffer, "class_findmethod: method:");
2690 utf_sprint(buffer + strlen(buffer), name);
2691 strcpy(buffer + strlen(buffer), ", desc: ");
2692 utf_sprint(buffer + strlen(buffer), desc);
2693 strcpy(buffer + strlen(buffer), ", classname: ");
2694 utf_sprint(buffer + strlen(buffer), c->name);
2698 MFREE(buffer, char, buffer_len);
2700 for (i = 0; i < c->methodscount; i++) {
2701 #ifdef JOWENN_DEBUG2
2703 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2705 buffer = MNEW(char, buffer_len);
2707 strcpy(buffer, "class_findmethod: comparing to method:");
2708 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2709 strcpy(buffer + strlen(buffer), ", desc: ");
2710 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2714 MFREE(buffer, char, buffer_len);
2717 if ((c->methods[i].name == name) && ((desc == NULL) ||
2718 (c->methods[i].descriptor == desc))) {
2719 return &(c->methods[i]);
2722 #ifdef JOWENN_DEBUG2
2723 class_showconstantpool(c);
2724 log_text("class_findmethod: returning NULL");
2729 s4 idx=class_findmethodIndex(c, name, desc);
2730 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2731 if (idx == -1) return NULL;
2733 return &(c->methods[idx]);
2737 /*********************** Function: class_fetchmethod **************************
2739 like class_findmethod, but aborts with an error if the method is not found
2741 *******************************************************************************/
2743 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2746 mi = class_findmethod(c, name, desc);
2749 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2750 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2751 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2752 panic("Method not found");
2759 /*********************** Function: class_findmethod_w**************************
2761 like class_findmethod, but logs a warning if the method is not found
2763 *******************************************************************************/
2765 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2768 mi = class_findmethod(c, name, desc);
2771 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2772 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2773 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2775 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2776 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2777 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2778 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2779 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2780 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2781 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2782 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2783 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2784 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2785 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2788 log_plain(" : WARNING: Method not found");log_nl( );
2795 /************************* Function: class_findmethod_approx ******************
2797 like class_findmethod but ignores the return value when comparing the
2800 *******************************************************************************/
2802 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2806 for (i = 0; i < c->methodscount; i++) {
2807 if (c->methods[i].name == name) {
2808 utf *meth_descr = c->methods[i].descriptor;
2812 return &(c->methods[i]);
2814 if (desc->blength <= meth_descr->blength) {
2815 /* current position in utf text */
2816 char *desc_utf_ptr = desc->text;
2817 char *meth_utf_ptr = meth_descr->text;
2818 /* points behind utf strings */
2819 char *desc_end = utf_end(desc);
2820 char *meth_end = utf_end(meth_descr);
2823 /* compare argument types */
2824 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2826 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2827 break; /* no match */
2830 return &(c->methods[i]); /* all parameter types equal */
2840 /***************** Function: class_resolvemethod_approx ***********************
2842 Searches a class and every super class for a method (without paying
2843 attention to the return value)
2845 *******************************************************************************/
2847 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2850 /* search for method (ignore returntype) */
2851 methodinfo *m = class_findmethod_approx(c, name, desc);
2854 /* search superclass */
2862 /************************* Function: class_resolvemethod ***********************
2864 Searches a class and every super class for a method.
2866 *******************************************************************************/
2868 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2871 methodinfo *m = class_findmethod(c, name, desc);
2873 /* search superclass */
2881 /************************* Function: class_issubclass **************************
2883 Checks if sub is a descendant of super.
2885 *******************************************************************************/
2887 bool class_issubclass(classinfo *sub, classinfo *super)
2890 if (!sub) return false;
2891 if (sub == super) return true;
2897 /****************** Initialization function for classes ******************
2899 In Java, every class can have a static initialization function. This
2900 function has to be called BEFORE calling other methods or accessing static
2903 *******************************************************************************/
2905 void class_init(classinfo *c)
2908 native_stackframeinfo **info;
2910 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2914 if (!makeinitializations)
2919 c->initialized = true;
2922 count_class_inits++;
2925 /* initialize super class */
2928 char logtext[MAXLOGTEXT];
2929 sprintf(logtext, "Initialize super class ");
2930 utf_sprint(logtext + strlen(logtext), c->super->name);
2931 sprintf(logtext + strlen(logtext), " from ");
2932 utf_sprint(logtext + strlen(logtext), c->name);
2935 class_init(c->super);
2938 /* initialize interface classes */
2939 for (i = 0; i < c->interfacescount; i++) {
2941 char logtext[MAXLOGTEXT];
2942 sprintf(logtext, "Initialize interface class ");
2943 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2944 sprintf(logtext + strlen(logtext), " from ");
2945 utf_sprint(logtext + strlen(logtext), c->name);
2948 class_init(c->interfaces[i]); /* real */
2951 m = class_findmethod(c, utf_clinit, utf_fidesc);
2954 char logtext[MAXLOGTEXT];
2955 sprintf(logtext, "Class ");
2956 utf_sprint(logtext + strlen(logtext), c->name);
2957 sprintf(logtext + strlen(logtext), " has no initializer");
2960 /* goto callinitialize;*/
2964 if (!(m->flags & ACC_STATIC))
2965 panic("Class initializer is not static!");
2968 char logtext[MAXLOGTEXT];
2969 sprintf(logtext, "Starting initializer for class: ");
2970 utf_sprint(logtext + strlen(logtext), c->name);
2974 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2979 /* now call the initializer */
2980 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2982 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2983 assert(blockInts == 0);
2987 /* we have to throw an exception */
2988 if (*exceptionptr) {
2989 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2990 printf("Caused by: ");
2991 utf_display((*exceptionptr)->vftbl->class->name);
2993 /* do we have a detail message? */
2994 if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
2996 utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
3005 char logtext[MAXLOGTEXT];
3006 sprintf(logtext, "Finished initializer for class: ");
3007 utf_sprint(logtext + strlen(logtext), c->name);
3011 if (c->name == utf_systemclass) {
3012 /* class java.lang.System requires explicit initialization */
3015 printf("#### Initializing class System");
3017 /* find initializing method */
3018 m = class_findmethod(c,
3019 utf_initsystemclass,
3023 /* no method found */
3024 /* printf("initializeSystemClass failed"); */
3028 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3033 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3035 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3036 assert(blockInts == 0);
3040 if (*exceptionptr) {
3041 printf("#### initializeSystemClass has thrown: ");
3042 utf_display((*exceptionptr)->vftbl->class->name);
3050 /********* Function: find_class_method_constant *********/
3052 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3057 for (i=0; i<c->cpcount; i++) {
3059 e = c -> cpinfos [i];
3062 switch (c -> cptags [i]) {
3063 case CONSTANT_Methodref:
3065 constant_FMIref *fmi = e;
3066 if ( (fmi->class->name == c1)
3067 && (fmi->name == m1)
3068 && (fmi->descriptor == d1)) {
3075 case CONSTANT_InterfaceMethodref:
3077 constant_FMIref *fmi = e;
3078 if ( (fmi->class->name == c1)
3079 && (fmi->name == m1)
3080 && (fmi->descriptor == d1)) {
3094 void class_showconstanti(classinfo *c, int ii)
3100 printf ("#%d: ", (int) i);
3102 switch (c->cptags [i]) {
3103 case CONSTANT_Class:
3104 printf("Classreference -> ");
3105 utf_display(((classinfo*)e)->name);
3108 case CONSTANT_Fieldref:
3109 printf("Fieldref -> "); goto displayFMIi;
3110 case CONSTANT_Methodref:
3111 printf("Methodref -> "); goto displayFMIi;
3112 case CONSTANT_InterfaceMethodref:
3113 printf("InterfaceMethod -> "); goto displayFMIi;
3116 constant_FMIref *fmi = e;
3117 utf_display(fmi->class->name);
3119 utf_display(fmi->name);
3121 utf_display(fmi->descriptor);
3125 case CONSTANT_String:
3126 printf("String -> ");
3129 case CONSTANT_Integer:
3130 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3132 case CONSTANT_Float:
3133 printf("Float -> %f", ((constant_float*)e)->value);
3135 case CONSTANT_Double:
3136 printf("Double -> %f", ((constant_double*)e)->value);
3140 u8 v = ((constant_long*)e)->value;
3142 printf("Long -> %ld", (long int) v);
3144 printf("Long -> HI: %ld, LO: %ld\n",
3145 (long int) v.high, (long int) v.low);
3149 case CONSTANT_NameAndType:
3151 constant_nameandtype *cnt = e;
3152 printf("NameAndType: ");
3153 utf_display(cnt->name);
3155 utf_display(cnt->descriptor);
3163 panic("Invalid type of ConstantPool-Entry");
3170 void class_showconstantpool (classinfo *c)
3175 printf ("---- dump of constant pool ----\n");
3177 for (i=0; i<c->cpcount; i++) {
3178 printf ("#%d: ", (int) i);
3180 e = c -> cpinfos [i];
3183 switch (c -> cptags [i]) {
3184 case CONSTANT_Class:
3185 printf ("Classreference -> ");
3186 utf_display ( ((classinfo*)e) -> name );
3189 case CONSTANT_Fieldref:
3190 printf ("Fieldref -> "); goto displayFMI;
3191 case CONSTANT_Methodref:
3192 printf ("Methodref -> "); goto displayFMI;
3193 case CONSTANT_InterfaceMethodref:
3194 printf ("InterfaceMethod -> "); goto displayFMI;
3197 constant_FMIref *fmi = e;
3198 utf_display ( fmi->class->name );
3200 utf_display ( fmi->name);
3202 utf_display ( fmi->descriptor );
3206 case CONSTANT_String:
3207 printf ("String -> ");
3210 case CONSTANT_Integer:
3211 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3213 case CONSTANT_Float:
3214 printf ("Float -> %f", ((constant_float*)e) -> value);
3216 case CONSTANT_Double:
3217 printf ("Double -> %f", ((constant_double*)e) -> value);
3221 u8 v = ((constant_long*)e) -> value;
3223 printf ("Long -> %ld", (long int) v);
3225 printf ("Long -> HI: %ld, LO: %ld\n",
3226 (long int) v.high, (long int) v.low);
3230 case CONSTANT_NameAndType:
3232 constant_nameandtype *cnt = e;
3233 printf ("NameAndType: ");
3234 utf_display (cnt->name);
3236 utf_display (cnt->descriptor);
3240 printf ("Utf8 -> ");
3244 panic ("Invalid type of ConstantPool-Entry");
3254 /********** Function: class_showmethods (debugging only) *************/
3256 void class_showmethods (classinfo *c)
3260 printf ("--------- Fields and Methods ----------------\n");
3261 printf ("Flags: "); printflags (c->flags); printf ("\n");
3263 printf ("This: "); utf_display (c->name); printf ("\n");
3265 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3267 printf ("Index: %d\n", c->index);
3269 printf ("interfaces:\n");
3270 for (i=0; i < c-> interfacescount; i++) {
3272 utf_display (c -> interfaces[i] -> name);
3273 printf (" (%d)\n", c->interfaces[i] -> index);
3276 printf ("fields:\n");
3277 for (i=0; i < c -> fieldscount; i++) {
3278 field_display (&(c -> fields[i]));
3281 printf ("methods:\n");
3282 for (i=0; i < c -> methodscount; i++) {
3283 methodinfo *m = &(c->methods[i]);
3284 if ( !(m->flags & ACC_STATIC))
3285 printf ("vftblindex: %d ", m->vftblindex);
3287 method_display ( m );
3291 printf ("Virtual function table:\n");
3292 for (i=0; i<c->vftbl->vftbllength; i++) {
3293 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3300 /******************************************************************************/
3301 /******************* General functions for the class loader *******************/
3302 /******************************************************************************/
3304 /********************* Function: loader_load ***********************************
3306 Loads and links the class desired class and each class and interface
3308 Returns: a pointer to this class
3310 *******************************************************************************/
3312 static int loader_load_running = 0;
3314 classinfo *loader_load(utf *topname)
3320 classinfo *notlinkable;
3322 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3323 pthread_mutex_lock(&compiler_mutex);
3326 /* avoid recursive calls */
3327 if (loader_load_running)
3328 return class_new(topname);
3330 loader_load_running++;
3332 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3337 starttime = getcputime();
3339 top = class_new(topname);
3342 while ((c = list_first(&unloadedclasses))) {
3343 if (!class_load(c)) {
3345 dolog("Failed to load class");
3346 list_remove(&unloadedclasses, c);
3353 dolog("Linking...");
3355 /* Added a hack to break infinite linking loops. A better
3356 * linking algorithm would be nice. -Edwin */
3358 while ((c = list_first(&unlinkedclasses))) {
3363 else if (notlinkable == c) {
3364 /* We tried to link this class for the second time and
3365 * no other classes were linked in between, so we are
3369 dolog("Cannot resolve linking dependencies");
3372 throw_linkageerror_message(c->name);
3380 dolog("Linking done.");
3383 loader_compute_subclasses();
3386 if (getloadingtime) {
3387 stoptime = getcputime();
3388 loadingtime += (stoptime - starttime);
3392 loader_load_running--;
3394 /* check if a former loader_load call tried to load/link the class and
3395 failed. This is needed because the class didn't appear in the
3396 undloadclasses or unlinkedclasses list during this class. */
3399 if (linkverbose) dolog("Failed to load class (former call)");
3400 throw_noclassdeffounderror_message(top->name);
3403 } else if (!top->linked) {
3405 dolog("Failed to link class (former call)");
3406 throw_linkageerror_message(top->name);
3411 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3415 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3416 pthread_mutex_unlock(&compiler_mutex);
3419 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3425 /****************** Function: loader_load_sysclass ****************************
3427 Loads and links the class desired class and each class and interface
3430 The pointer to the classinfo is stored in *top if top != NULL.
3431 The pointer is also returned.
3433 If the class could not be loaded the function aborts with an error.
3435 *******************************************************************************/
3437 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3441 if ((cls = loader_load(topname)) == NULL) {
3442 log_plain("Could not load important system class: ");
3443 log_plain_utf(topname);
3445 panic("Could not load important system class");
3448 if (top) *top = cls;
3454 /**************** function: create_primitive_classes ***************************
3456 create classes representing primitive types
3458 ********************************************************************************/
3460 void create_primitive_classes()
3464 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3465 /* create primitive class */
3466 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3467 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3468 c -> impldBy = NULL;
3470 /* prevent loader from loading primitive class */
3471 list_remove (&unloadedclasses, c);
3473 /* add to unlinked classes */
3474 list_addlast (&unlinkedclasses, c);
3475 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3478 primitivetype_table[i].class_primitive = c;
3480 /* create class for wrapping the primitive type */
3481 primitivetype_table[i].class_wrap =
3482 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3483 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3484 primitivetype_table[i].class_wrap -> impldBy = NULL;
3486 /* create the primitive array class */
3487 if (primitivetype_table[i].arrayname) {
3488 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3489 primitivetype_table[i].arrayclass = c;
3491 if (!c->linked) class_link(c);
3492 primitivetype_table[i].arrayvftbl = c->vftbl;
3497 /**************** function: class_primitive_from_sig ***************************
3499 return the primitive class indicated by the given signature character
3501 If the descriptor does not indicate a valid primitive type the
3502 return value is NULL.
3504 ********************************************************************************/
3506 classinfo *class_primitive_from_sig(char sig)
3509 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3510 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3511 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3512 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3513 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3514 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3515 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3516 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3517 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3522 /****************** function: class_from_descriptor ****************************
3524 return the class indicated by the given descriptor
3526 utf_ptr....first character of descriptor
3527 end_ptr....first character after the end of the string
3528 next.......if non-NULL, *next is set to the first character after
3529 the descriptor. (Undefined if an error occurs.)
3531 mode.......a combination (binary or) of the following flags:
3533 (Flags marked with * are the default settings.)
3535 What to do if a reference type descriptor is parsed successfully:
3537 CLASSLOAD_SKIP...skip it and return something != NULL
3538 * CLASSLOAD_NEW....get classinfo * via class_new
3539 CLASSLOAD_LOAD...get classinfo * via loader_load
3541 How to handle primitive types:
3543 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3544 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3546 How to handle "V" descriptors:
3548 * CLASSLOAD_VOID.....handle it like other primitive types
3549 CLASSLOAD_NOVOID...treat it as an error
3551 How to deal with extra characters after the end of the
3554 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3555 CLASSLOAD_CHECKEND.....treat them as an error
3557 How to deal with errors:
3559 * CLASSLOAD_PANIC....abort execution with an error message
3560 CLASSLOAD_NOPANIC..return NULL on error
3562 ********************************************************************************/
3564 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3565 char **next, int mode)
3567 char *start = utf_ptr;
3571 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3573 if (mode & CLASSLOAD_CHECKEND)
3574 error |= (utf_ptr != end_ptr);
3577 if (next) *next = utf_ptr;
3581 if (mode & CLASSLOAD_NOVOID)
3592 return (mode & CLASSLOAD_NULLPRIMITIVE)
3594 : class_primitive_from_sig(*start);
3601 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3602 name = utf_new(start, utf_ptr - start);
3603 return (mode & CLASSLOAD_LOAD)
3604 ? loader_load(name) : class_new(name); /* XXX handle errors */
3608 /* An error occurred */
3609 if (mode & CLASSLOAD_NOPANIC)
3612 log_plain("Invalid descriptor at beginning of '");
3613 log_plain_utf(utf_new(start, end_ptr - start));
3617 panic("Invalid descriptor");
3619 /* keep compiler happy */
3624 /******************* function: type_from_descriptor ****************************
3626 return the basic type indicated by the given descriptor
3628 This function parses a descriptor and returns its basic type as
3629 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3631 cls...if non-NULL the referenced variable is set to the classinfo *
3632 returned by class_from_descriptor.
3634 For documentation of the arguments utf_ptr, end_ptr, next and mode
3635 see class_from_descriptor. The only difference is that
3636 type_from_descriptor always uses CLASSLOAD_PANIC.
3638 ********************************************************************************/
3640 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3641 char **next, int mode)
3644 if (!cls) cls = &mycls;
3645 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3662 return TYPE_ADDRESS;
3667 /*************** function: create_system_exception_classes *******************************
3669 create system exception classes needed by default
3671 ********************************************************************************/
3673 static void create_system_exception_classes()
3676 log_text("loader_init: create_system_exception_classs: loader_load: java/lang/ClassCastException");
3678 loader_load_sysclass(&class_java_lang_ClassCastException,
3679 utf_new_char("java/lang/ClassCastException"));
3680 loader_load_sysclass(&class_java_lang_NullPointerException,
3681 utf_new_char("java/lang/NullPointerException"));
3682 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3683 utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
3684 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3685 utf_new_char("java/lang/NegativeArraySizeException"));
3686 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3687 utf_new_char("java/lang/OutOfMemoryError"));
3688 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3689 utf_new_char("java/lang/ArrayStoreException"));
3690 loader_load_sysclass(&class_java_lang_ArithmeticException,
3691 utf_new_char("java/lang/ArithmeticException"));
3692 loader_load_sysclass(&class_java_lang_ThreadDeath,
3693 utf_new_char("java/lang/ThreadDeath"));
3697 /*************** function: create_system_exception_classes *******************************
3699 create system exception proto classes needed by default
3701 ********************************************************************************/
3703 static void create_system_exception_proto_classes()
3706 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3707 proto_java_lang_ClassCastException =
3708 builtin_new(class_java_lang_ClassCastException);
3710 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3712 proto_java_lang_NullPointerException =
3713 builtin_new(class_java_lang_NullPointerException);
3714 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3716 proto_java_lang_ArrayIndexOutOfBoundsException =
3717 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3719 proto_java_lang_NegativeArraySizeException =
3720 builtin_new(class_java_lang_NegativeArraySizeException);
3722 proto_java_lang_OutOfMemoryError =
3723 builtin_new(class_java_lang_OutOfMemoryError);
3725 proto_java_lang_ArithmeticException =
3726 builtin_new(class_java_lang_ArithmeticException);
3728 proto_java_lang_ArrayStoreException =
3729 builtin_new(class_java_lang_ArrayStoreException);
3731 proto_java_lang_ThreadDeath =
3732 builtin_new(class_java_lang_ThreadDeath);
3739 /*************** function: create_pseudo_classes *******************************
3741 create pseudo classes used by the typechecker
3743 ********************************************************************************/
3745 static void create_pseudo_classes()
3747 /* pseudo class for Arraystubs (extends java.lang.Object) */
3749 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3750 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3752 pseudo_class_Arraystub->super = class_java_lang_Object;
3753 pseudo_class_Arraystub->interfacescount = 2;
3754 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3755 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3756 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3758 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3759 class_link(pseudo_class_Arraystub);
3761 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3763 /* pseudo class representing the null type */
3765 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3766 list_remove(&unloadedclasses, pseudo_class_Null);
3768 pseudo_class_Null->super = class_java_lang_Object;
3770 list_addlast(&unlinkedclasses, pseudo_class_Null);
3771 class_link(pseudo_class_Null);
3773 /* pseudo class representing new uninitialized objects */
3775 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3776 list_remove(&unloadedclasses, pseudo_class_New);
3778 pseudo_class_New->super = class_java_lang_Object;
3780 list_addlast(&unlinkedclasses, pseudo_class_New);
3781 class_link(pseudo_class_New);
3785 /********************** Function: loader_init **********************************
3787 Initializes all lists and loads all classes required for the system or the
3790 *******************************************************************************/
3792 void loader_init(u1 *stackbottom)
3796 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3797 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3798 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3800 /* create utf-symbols for pointer comparison of frequently used strings */
3801 utf_innerclasses = utf_new_char("InnerClasses");
3802 utf_constantvalue = utf_new_char("ConstantValue");
3803 utf_code = utf_new_char("Code");
3804 utf_exceptions = utf_new_char("Exceptions");
3805 utf_linenumbertable = utf_new_char("LineNumberTable");
3806 utf_finalize = utf_new_char("finalize");
3807 utf_fidesc = utf_new_char("()V");
3808 utf_init = utf_new_char("<init>");
3809 utf_clinit = utf_new_char("<clinit>");
3810 utf_initsystemclass = utf_new_char("initializeSystemClass");
3811 utf_systemclass = utf_new_char("java/lang/System");
3812 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3813 utf_initialize = utf_new_char("initialize");
3814 utf_initializedesc = utf_new_char("(I)V");
3816 utf_vmclass = utf_new_char("java/lang/VMClass");
3817 utf_java_lang_Object= utf_new_char("java/lang/Object");
3819 array_packagename = utf_new_char("<the array package>");
3821 /* create some important classes */
3822 /* These classes have to be created now because the classinfo
3823 * pointers are used in the loading code.
3825 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3826 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3827 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3828 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3830 if (verbose) log_text("loader_init: java/lang/Object");
3831 /* load the classes which were created above */
3832 loader_load_sysclass(NULL, class_java_lang_Object->name);
3834 loader_inited = 1; /*JOWENN*/
3836 loader_load_sysclass(&class_java_lang_Throwable,
3837 utf_new_char("java/lang/Throwable"));
3839 create_system_exception_classes();
3841 /* create classes representing primitive types */
3842 create_primitive_classes();
3844 /* create classes used by the typechecker */
3845 create_pseudo_classes();
3847 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3848 stringtable_update();
3850 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3854 create_system_exception_proto_classes();
3860 /********************* Function: loader_initclasses ****************************
3862 Initializes all loaded but uninitialized classes
3864 *******************************************************************************/
3867 /* XXX TWISTI: i think we do not need this */
3868 void loader_initclasses ()
3872 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3873 pthread_mutex_lock(&compiler_mutex);
3876 intsDisable(); /* schani */
3878 if (makeinitializations) {
3879 c = list_first(&linkedclasses);
3882 c = list_next(&linkedclasses, c);
3886 intsRestore(); /* schani */
3888 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3889 pthread_mutex_unlock(&compiler_mutex);
3895 static void loader_compute_class_values(classinfo *c)
3899 c->vftbl->baseval = ++classvalue;
3902 while (subs != NULL) {
3903 loader_compute_class_values(subs);
3904 subs = subs->nextsub;
3906 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3911 for (i = 0; i < c->index; i++)
3913 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3914 utf_display(c->name);
3921 void loader_compute_subclasses()
3925 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3926 intsDisable(); /* schani */
3929 c = list_first(&linkedclasses);
3931 if (!(c->flags & ACC_INTERFACE)) {
3935 c = list_next(&linkedclasses, c);
3938 c = list_first(&linkedclasses);
3940 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3941 c->nextsub = c->super->sub;
3944 c = list_next(&linkedclasses, c);
3948 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3951 loader_compute_class_values(class_java_lang_Object);
3952 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3956 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3957 intsRestore(); /* schani */
3962 /******************** function classloader_buffer ******************************
3964 sets buffer for reading classdata
3966 *******************************************************************************/
3968 void classload_buffer(u1 *buf, int len)
3971 classbuffer_size = len;
3972 classbuf_pos = buf - 1;
3976 /******************** Function: loader_close ***********************************
3980 *******************************************************************************/
3986 while ((c = list_first(&unloadedclasses))) {
3987 list_remove(&unloadedclasses, c);
3988 /* class_free(c); */
3990 while ((c = list_first(&unlinkedclasses))) {
3991 list_remove(&unlinkedclasses, c);
3992 /* class_free(c); */
3994 while ((c = list_first(&linkedclasses))) {
3995 list_remove(&linkedclasses, c);
3996 /* class_free(c); */
4002 * These are local overrides for various environment variables in Emacs.
4003 * Please do not remove this and leave it at the end of the file, where
4004 * Emacs will automagically detect them.
4005 * ---------------------------------------------------------------------
4008 * indent-tabs-mode: t