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 999 2004-03-30 22:34:40Z 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_sourcefile; /*SourceFile*/
91 static utf *utf_finalize; /* finalize */
92 static utf *utf_fidesc; /* ()V changed */
93 static utf *utf_init; /* <init> */
94 static utf *utf_clinit; /* <clinit> */
95 static utf *utf_initsystemclass; /* initializeSystemClass */
96 static utf *utf_systemclass; /* java/lang/System */
97 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
98 static utf *utf_vmclass; /* java/lang/VMClassLoader */
99 static utf *utf_initialize;
100 static utf *utf_initializedesc;
101 static utf *utf_java_lang_Object; /* java/lang/Object */
114 /* important system classes ***************************************************/
116 classinfo *class_java_lang_Object;
117 classinfo *class_java_lang_String;
119 classinfo *class_java_lang_Throwable;
120 classinfo *class_java_lang_Cloneable;
121 classinfo *class_java_io_Serializable;
123 /* Pseudo classes for the typechecker */
124 classinfo *pseudo_class_Arraystub = NULL;
125 classinfo *pseudo_class_Null = NULL;
126 classinfo *pseudo_class_New = NULL;
127 vftbl *pseudo_class_Arraystub_vftbl = NULL;
129 utf *array_packagename = NULL;
131 static int loader_inited = 0;
134 /********************************************************************
135 list of classpath entries (either filesystem directories or
137 ********************************************************************/
138 static classpath_info *classpath_entries=0;
141 /******************************************************************************
143 structure for primitive classes: contains the class for wrapping the
144 primitive type, the primitive class, the name of the class for wrapping,
145 the one character type signature and the name of the primitive class
147 ******************************************************************************/
149 /* CAUTION: Don't change the order of the types. This table is indexed
150 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
152 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
153 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
154 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
155 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
156 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
157 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
158 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
159 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
160 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
161 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
165 /* instances of important system classes **************************************/
167 java_objectheader *proto_java_lang_NullPointerException;
170 /************* functions for reading classdata *********************************
172 getting classdata in blocks of variable size
173 (8,16,32,64-bit integer or float)
175 *******************************************************************************/
177 static char *classpath = ""; /* searchpath for classfiles */
178 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
179 static u1 *classbuf_pos; /* current position in classfile buffer */
180 static int classbuffer_size; /* size of classfile-data */
182 /* assert that at least <len> bytes are left to read */
183 /* <len> is limited to the range of non-negative s4 values */
184 #define ASSERT_LEFT(len) \
185 do {if ( ((s4)(len)) < 0 \
186 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
187 panic("Unexpected end of classfile"); } while(0)
189 /* transfer block of classfile data into a buffer */
191 #define suck_nbytes(buffer,len) \
192 do {ASSERT_LEFT(len); \
193 memcpy(buffer,classbuf_pos+1,len); \
194 classbuf_pos+=len;} while (0)
196 /* skip block of classfile data */
198 #define skip_nbytes(len) \
199 do {ASSERT_LEFT(len); \
200 classbuf_pos+=len;} while(0)
206 return *++classbuf_pos;
214 return ((u2) a << 8) + (u2) b;
224 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
227 #define suck_s8() (s8) suck_u8()
228 #define suck_s2() (s2) suck_u2()
229 #define suck_s4() (s4) suck_u4()
230 #define suck_s1() (s1) suck_u1()
233 /* get u8 from classfile data */
240 return (hi << 32) + lo;
250 /* get float from classfile data */
251 static float suck_float()
258 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
259 memcpy((u1*) (&f), buffer, 4);
261 suck_nbytes((u1*) (&f), 4);
264 PANICIF (sizeof(float) != 4, "Incompatible float-format");
270 /* get double from classfile data */
271 static double suck_double()
278 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
279 memcpy((u1*) (&d), buffer, 8);
281 suck_nbytes((u1*) (&d), 8);
284 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
290 /************************** function suck_init *********************************
292 called once at startup, sets the searchpath for the classfiles
294 *******************************************************************************/
296 void suck_init(char *cpath)
303 union classpath_info *tmp;
304 union classpath_info *insertAfter=0;
309 if (classpath_entries) panic("suck_init should be called only once");
310 for(start=classpath;(*start)!='\0';) {
311 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
314 filenamelen=(end-start);
348 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
349 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
350 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
353 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
354 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
355 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
360 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
362 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
363 strncpy(filename,start,filenamelen);
364 filename[filenamelen+1]='\0';
369 unzFile uf=unzOpen(filename);
371 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
372 tmp->archive.type=CLASSPATH_ARCHIVE;
378 panic("Zip/JAR not supported");
382 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
383 tmp->filepath.type=CLASSPATH_PATH;
384 tmp->filepath.next=0;
385 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
386 filename[filenamelen]='/';
387 filename[filenamelen+1]='\0';
391 tmp->filepath.filename=filename;
392 tmp->filepath.pathlen=filenamelen;
398 insertAfter->filepath.next=tmp;
400 classpath_entries=tmp;
405 if ((*end)==':') start=end+1; else start=end;
408 if (filename!=0) free(filename);
413 /************************** function suck_start ********************************
415 returns true if classbuffer is already loaded or a file for the
416 specified class has succussfully been read in. All directories of
417 the searchpath are used to find the classfile (<classname>.class).
418 Returns false if no classfile is found and writes an error message.
420 *******************************************************************************/
422 bool suck_start(utf *classname)
424 classpath_info *currPos;
427 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
433 if (classbuffer) return true; /* classbuffer is already valid */
435 utf_ptr = classname->text;
436 while (utf_ptr < utf_end(classname)) {
437 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
439 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
441 filename[filenamelen++] = c;
443 strcpy(filename + filenamelen, ".class");
445 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
447 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
448 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
449 unz_file_info file_info;
450 /*log_text("Class found in zip file");*/
451 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
452 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
453 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
454 classbuffer_size = file_info.uncompressed_size;
455 classbuffer = MNEW(u1, classbuffer_size);
456 classbuf_pos = classbuffer - 1;
457 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
458 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
459 unzCloseCurrentFile(currPos->archive.uf);
462 MFREE(classbuffer, u1, classbuffer_size);
463 log_text("Error while unzipping");
465 } else log_text("Error while opening file in archive");
466 } else log_text("Error while retrieving fileinfo");
468 unzCloseCurrentFile(currPos->archive.uf);
472 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
473 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
474 classfile = fopen(currPos->filepath.filename, "r");
475 if (classfile) { /* file exists */
477 /* determine size of classfile */
479 /* dolog("File: %s",filename); */
481 err = stat(currPos->filepath.filename, &buffer);
483 if (!err) { /* read classfile data */
484 classbuffer_size = buffer.st_size;
485 classbuffer = MNEW(u1, classbuffer_size);
486 classbuf_pos = classbuffer - 1;
487 fread(classbuffer, 1, classbuffer_size, classfile);
498 dolog("Warning: Can not open class file '%s'", filename);
505 /************************** function suck_stop *********************************
507 frees memory for buffer with classfile data.
508 Caution: this function may only be called if buffer has been allocated
509 by suck_start with reading a file
511 *******************************************************************************/
515 /* determine amount of classdata not retrieved by suck-operations */
517 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
519 if (classdata_left > 0) {
521 dolog("There are %d extra bytes at end of classfile",
523 /* The JVM spec disallows extra bytes. */
524 panic("Extra bytes at end of classfile");
529 MFREE(classbuffer, u1, classbuffer_size);
534 /******************************************************************************/
535 /******************* Some support functions ***********************************/
536 /******************************************************************************/
538 void fprintflags (FILE *fp, u2 f)
540 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
541 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
542 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
543 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
544 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
545 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
546 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
547 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
548 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
549 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
550 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
554 /********** internal function: printflags (only for debugging) ***************/
556 void printflags(u2 f)
558 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
559 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
560 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
561 if ( f & ACC_STATIC ) printf (" STATIC");
562 if ( f & ACC_FINAL ) printf (" FINAL");
563 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
564 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
565 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
566 if ( f & ACC_NATIVE ) printf (" NATIVE");
567 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
568 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
572 /************************* Function: skipattribute *****************************
574 skips a (1) 'attribute' structure in the class file
576 *******************************************************************************/
578 static void skipattribute()
587 /********************** Function: skipattributebody ****************************
589 skips an attribute after the 16 bit reference to attribute_name has already
592 *******************************************************************************/
594 static void skipattributebody()
602 /************************* Function: skipattributes ****************************
604 skips num attribute structures
606 *******************************************************************************/
608 static void skipattributes(u4 num)
611 for (i = 0; i < num; i++)
616 /******************** function: innerclass_getconstant ************************
618 like class_getconstant, but if cptags is ZERO null is returned
620 *******************************************************************************/
622 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
624 /* invalid position in constantpool */
625 if (pos >= c->cpcount)
626 panic("Attempt to access constant outside range");
628 /* constantpool entry of type 0 */
632 /* check type of constantpool entry */
633 if (c->cptags[pos] != ctype) {
634 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
635 (int) ctype, (int) c->cptags[pos] );
638 return c->cpinfos[pos];
642 /************************ function: attribute_load ****************************
644 read attributes from classfile
646 *******************************************************************************/
648 static void attribute_load(u4 num, classinfo *c)
652 for (i = 0; i < num; i++) {
653 /* retrieve attribute name */
654 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
656 if (aname == utf_innerclasses) {
657 /* innerclasses attribute */
659 if (c->innerclass != NULL)
660 panic("Class has more than one InnerClasses attribute");
662 /* skip attribute length */
664 /* number of records */
665 c->innerclasscount = suck_u2();
666 /* allocate memory for innerclass structure */
667 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
669 for (j = 0; j < c->innerclasscount; j++) {
670 /* The innerclass structure contains a class with an encoded name,
671 its defining scope, its simple name and a bitmask of the access flags.
672 If an inner class is not a member, its outer_class is NULL,
673 if a class is anonymous, its name is NULL. */
675 innerclassinfo *info = c->innerclass + j;
677 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
678 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
679 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
680 info->flags = suck_u2(); /* access_flags bitmask */
682 } else if (aname==utf_sourcefile) {
684 /*log_text("source file attribute found");*/
685 c->sourcefile = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
687 /* unknown attribute */
694 /******************* function: checkfielddescriptor ****************************
696 checks whether a field-descriptor is valid and aborts otherwise
697 all referenced classes are inserted into the list of unloaded classes
699 *******************************************************************************/
701 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
703 class_from_descriptor(utf_ptr,end_pos,NULL,
705 | CLASSLOAD_NULLPRIMITIVE
707 | CLASSLOAD_CHECKEND);
709 /* XXX use the following if -noverify */
711 char *tstart; /* pointer to start of classname */
713 char *start = utf_ptr;
715 switch (*utf_ptr++) {
729 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
730 panic ("Ill formed descriptor");
734 panic ("Ill formed descriptor");
737 /* exceeding characters */
738 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
743 /******************* function checkmethoddescriptor ****************************
745 checks whether a method-descriptor is valid and aborts otherwise.
746 All referenced classes are inserted into the list of unloaded classes.
748 The number of arguments is returned. A long or double argument is counted
751 *******************************************************************************/
753 static int checkmethoddescriptor (utf *d)
755 char *utf_ptr = d->text; /* current position in utf text */
756 char *end_pos = utf_end(d); /* points behind utf string */
757 int argcount = 0; /* number of arguments */
759 /* method descriptor must start with parenthesis */
760 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
762 /* check arguments */
763 while (utf_ptr != end_pos && *utf_ptr != ')') {
764 /* We cannot count the this argument here because
765 * we don't know if the method is static. */
766 if (*utf_ptr == 'J' || *utf_ptr == 'D')
770 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
772 | CLASSLOAD_NULLPRIMITIVE
776 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
777 utf_ptr++; /* skip ')' */
779 class_from_descriptor(utf_ptr,end_pos,NULL,
781 | CLASSLOAD_NULLPRIMITIVE
782 | CLASSLOAD_CHECKEND);
785 panic("Invalid method descriptor: too many arguments");
789 /* XXX use the following if -noverify */
791 /* check arguments */
792 while ((c = *utf_ptr++) != ')') {
809 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
810 panic ("Ill formed method descriptor");
814 panic ("Ill formed methodtype-descriptor");
818 /* check returntype */
820 /* returntype void */
821 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
824 /* treat as field-descriptor */
825 checkfielddescriptor (utf_ptr,end_pos);
830 /***************** Function: print_arraydescriptor ****************************
832 Debugging helper for displaying an arraydescriptor
834 *******************************************************************************/
836 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
839 fprintf(file, "<NULL>");
844 if (desc->componentvftbl) {
845 if (desc->componentvftbl->class)
846 utf_fprint(file, desc->componentvftbl->class->name);
848 fprintf(file, "<no classinfo>");
854 if (desc->elementvftbl) {
855 if (desc->elementvftbl->class)
856 utf_fprint(file, desc->elementvftbl->class->name);
858 fprintf(file, "<no classinfo>");
862 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
863 desc->dataoffset, desc->componentsize);
867 /******************************************************************************/
868 /************************** Functions for fields ****************************/
869 /******************************************************************************/
872 /************************ Function: field_load *********************************
874 Load everything about a class field from the class file and fill a
875 'fieldinfo' structure. For static fields, space in the data segment is
878 *******************************************************************************/
880 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
882 static void field_load(fieldinfo *f, classinfo *c)
886 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
888 f->flags = suck_u2(); /* ACC flags */
889 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
890 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
894 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
895 panic("Field with invalid name");
897 /* check flag consistency */
898 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
899 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
900 panic("Field has invalid access flags");
901 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
902 panic("Field is declared final and volatile");
903 if ((c->flags & ACC_INTERFACE) != 0) {
904 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
905 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
906 panic("Interface field is not declared static final public");
907 if ((f->flags & ACC_TRANSIENT) != 0)
908 panic("Interface field declared transient");
911 /* check descriptor */
912 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
915 f->type = jtype = desc_to_type(f->descriptor); /* data type */
916 f->offset = 0; /* offset from start of object */
921 case TYPE_INT: f->value.i = 0; break;
922 case TYPE_FLOAT: f->value.f = 0.0; break;
923 case TYPE_DOUBLE: f->value.d = 0.0; break;
924 case TYPE_ADDRESS: f->value.a = NULL; break;
927 f->value.l = 0; break;
929 f->value.l.low = 0; f->value.l.high = 0; break;
933 /* read attributes */
935 for (i = 0; i < attrnum; i++) {
938 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
940 if (aname != utf_constantvalue) {
941 /* unknown attribute */
945 /* constant value attribute */
947 if (pindex != field_load_NOVALUE)
948 panic("Field has more than one ConstantValue attribute");
950 /* check attribute length */
952 panic("ConstantValue attribute has invalid length");
954 /* index of value in constantpool */
957 /* initialize field with value from constantpool */
960 constant_integer *ci =
961 class_getconstant(c, pindex, CONSTANT_Integer);
962 f->value.i = ci->value;
968 class_getconstant(c, pindex, CONSTANT_Long);
969 f->value.l = cl->value;
975 class_getconstant(c, pindex, CONSTANT_Float);
976 f->value.f = cf->value;
981 constant_double *cd =
982 class_getconstant(c, pindex, CONSTANT_Double);
983 f->value.d = cd->value;
988 utf *u = class_getconstant(c, pindex, CONSTANT_String);
989 /* create javastring from compressed utf8-string */
990 f->value.a = literalstring_new(u);
995 log_text ("Invalid Constant - Type");
1002 /********************** function: field_free **********************************/
1004 static void field_free (fieldinfo *f)
1010 /**************** Function: field_display (debugging only) ********************/
1012 void field_display(fieldinfo *f)
1015 printflags(f->flags);
1017 utf_display(f->name);
1019 utf_display(f->descriptor);
1020 printf(" offset: %ld\n", (long int) (f->offset));
1024 /******************************************************************************/
1025 /************************* Functions for methods ******************************/
1026 /******************************************************************************/
1029 /*********************** Function: method_load *********************************
1031 Loads a method from the class file and fills an existing 'methodinfo'
1032 structure. For native methods, the function pointer field is set to the
1033 real function pointer, for JavaVM methods a pointer to the compiler is used
1036 *******************************************************************************/
1038 static void method_load(methodinfo *m, classinfo *c)
1044 count_all_methods++;
1046 m->thrownexceptionscount=0;
1047 m->linenumbercount=0;
1051 m->flags = suck_u2();
1052 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1055 if (!is_valid_name_utf(m->name))
1056 panic("Method with invalid name");
1057 if (m->name->text[0] == '<'
1058 && m->name != utf_init && m->name != utf_clinit)
1059 panic("Method with invalid special name");
1062 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1063 argcount = checkmethoddescriptor(m->descriptor);
1064 if ((m->flags & ACC_STATIC) == 0)
1065 argcount++; /* count the 'this' argument */
1069 panic("Method has more than 255 arguments");
1071 /* check flag consistency */
1072 if (m->name != utf_clinit) {
1073 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1074 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1075 panic("Method has invalid access flags");
1076 if ((m->flags & ACC_ABSTRACT) != 0) {
1077 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1078 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1079 panic("Abstract method has invalid flags set");
1081 if ((c->flags & ACC_INTERFACE) != 0) {
1082 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1083 != (ACC_ABSTRACT | ACC_PUBLIC))
1084 panic("Interface method is not declared abstract and public");
1086 if (m->name == utf_init) {
1087 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1088 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1089 panic("Instance initialization method has invalid flags set");
1095 m->exceptiontable = NULL;
1096 m->entrypoint = NULL;
1098 m->stubroutine = NULL;
1099 m->methodUsed = NOTUSED;
1102 m->subRedefsUsed = 0;
1106 if (!(m->flags & ACC_NATIVE)) {
1107 m->stubroutine = createcompilerstub(m);
1110 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1111 (m->flags & ACC_STATIC) != 0);
1113 m->stubroutine = createnativestub(f, m);
1118 attrnum = suck_u2();
1119 for (i = 0; i < attrnum; i++) {
1122 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1124 if (aname != utf_code) {
1125 if (aname == utf_exceptions) {
1128 suck_u4(); /*length*/
1129 exceptionCount=suck_u2();
1130 m->thrownexceptionscount=exceptionCount;
1131 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1132 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1133 (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(),CONSTANT_Class);
1137 skipattributebody();
1141 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1142 panic("Code attribute for native or abstract method");
1145 panic("Method has more than one Code attribute");
1148 m->maxstack = suck_u2();
1149 m->maxlocals = suck_u2();
1150 if (m->maxlocals < argcount)
1151 panic("max_locals is smaller than the number of arguments");
1153 codelen = suck_u4();
1155 panic("bytecode has zero length");
1156 if (codelen > 65536)
1157 panic("bytecode too long");
1158 m->jcodelength = codelen;
1159 m->jcode = MNEW(u1, m->jcodelength);
1160 suck_nbytes(m->jcode, m->jcodelength);
1161 m->exceptiontablelength = suck_u2();
1163 MNEW(exceptiontable, m->exceptiontablelength);
1166 count_vmcode_len += m->jcodelength + 18;
1167 count_extable_len += 8 * m->exceptiontablelength;
1170 for (e = 0; e < m->exceptiontablelength; e++) {
1172 m->exceptiontable[e].startpc = suck_u2();
1173 m->exceptiontable[e].endpc = suck_u2();
1174 m->exceptiontable[e].handlerpc = suck_u2();
1178 m->exceptiontable[e].catchtype = NULL;
1181 m->exceptiontable[e].catchtype =
1182 class_getconstant(c, idx, CONSTANT_Class);
1187 for (codeattrnum=suck_u2();codeattrnum>0;codeattrnum--) {
1188 utf * caname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1189 if (caname==utf_linenumbertable) {
1191 /*log_text("LineNumberTable found");*/
1193 m->linenumbercount=suck_u2();
1194 /*printf("length:%d\n",m->linenumbercount);*/
1195 m->linenumbers=MNEW(lineinfo,m->linenumbercount);
1196 for (lncid=0;lncid<m->linenumbercount;lncid++) {
1197 m->linenumbers[lncid].start_pc=suck_u2();
1198 m->linenumbers[lncid].line_number=suck_u2();
1201 skipattributes(codeattrnum);
1203 } else skipattributebody();
1210 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1211 panic("Method missing Code attribute");
1215 /********************* Function: method_free ***********************************
1217 frees all memory that was allocated for this method
1219 *******************************************************************************/
1221 static void method_free(methodinfo *m)
1224 MFREE(m->jcode, u1, m->jcodelength);
1226 if (m->exceptiontable)
1227 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1230 CFREE(m->mcode, m->mcodelength);
1232 if (m->stubroutine) {
1233 if (m->flags & ACC_NATIVE) {
1234 removenativestub(m->stubroutine);
1237 removecompilerstub(m->stubroutine);
1243 /************** Function: method_display (debugging only) **************/
1245 void method_display(methodinfo *m)
1248 printflags(m->flags);
1250 utf_display(m->name);
1252 utf_display(m->descriptor);
1256 /************** Function: method_display_flags_last (debugging only) **************/
1258 void method_display_flags_last(methodinfo *m)
1261 utf_display(m->name);
1263 utf_display(m->descriptor);
1265 printflags(m->flags);
1270 /******************** Function: method_canoverwrite ****************************
1272 Check if m and old are identical with respect to type and name. This means
1273 that old can be overwritten with m.
1275 *******************************************************************************/
1277 static bool method_canoverwrite(methodinfo *m, methodinfo *old)
1279 if (m->name != old->name) return false;
1280 if (m->descriptor != old->descriptor) return false;
1281 if (m->flags & ACC_STATIC) return false;
1288 /******************************************************************************/
1289 /************************ Functions for class *********************************/
1290 /******************************************************************************/
1293 /******************** function:: class_getconstant ******************************
1295 retrieves the value at position 'pos' of the constantpool of a class
1296 if the type of the value is other than 'ctype' the system is stopped
1298 *******************************************************************************/
1300 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1302 /* invalid position in constantpool */
1303 /* (pos == 0 is caught by type comparison) */
1304 if (pos >= c->cpcount)
1305 panic("Attempt to access constant outside range");
1307 /* check type of constantpool entry */
1309 if (c->cptags[pos] != ctype) {
1310 class_showconstantpool(c);
1311 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1312 (int) ctype, (int) c->cptags[pos]);
1315 return c->cpinfos[pos];
1319 /********************* Function: class_constanttype ****************************
1321 Determines the type of a class entry in the ConstantPool
1323 *******************************************************************************/
1325 u4 class_constanttype(classinfo *c, u4 pos)
1327 if (pos >= c->cpcount)
1328 panic("Attempt to access constant outside range");
1330 return c->cptags[pos];
1334 /******************** function: class_loadcpool ********************************
1336 loads the constantpool of a class,
1337 the entries are transformed into a simpler format
1338 by resolving references
1339 (a detailed overview of the compact structures can be found in global.h)
1341 *******************************************************************************/
1343 static void class_loadcpool(classinfo *c)
1346 /* The following structures are used to save information which cannot be
1347 processed during the first pass. After the complete constantpool has
1348 been traversed the references can be resolved.
1349 (only in specific order) */
1351 /* CONSTANT_Class_info entries */
1352 typedef struct forward_class {
1353 struct forward_class *next;
1358 /* CONSTANT_String */
1359 typedef struct forward_string {
1360 struct forward_string *next;
1365 /* CONSTANT_NameAndType */
1366 typedef struct forward_nameandtype {
1367 struct forward_nameandtype *next;
1371 } forward_nameandtype;
1373 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1374 typedef struct forward_fieldmethint {
1375 struct forward_fieldmethint *next;
1379 u2 nameandtype_index;
1380 } forward_fieldmethint;
1384 long int dumpsize = dump_size ();
1386 forward_class *forward_classes = NULL;
1387 forward_string *forward_strings = NULL;
1388 forward_nameandtype *forward_nameandtypes = NULL;
1389 forward_fieldmethint *forward_fieldmethints = NULL;
1391 /* number of entries in the constant_pool table plus one */
1392 u4 cpcount = c->cpcount = suck_u2();
1394 /* allocate memory */
1395 u1 *cptags = c->cptags = MNEW(u1, cpcount);
1396 voidptr *cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1399 panic("Invalid constant_pool_count (0)");
1402 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1405 /* initialize constantpool */
1406 for (idx = 0; idx < cpcount; idx++) {
1407 cptags[idx] = CONSTANT_UNUSED;
1408 cpinfos[idx] = NULL;
1412 /******* first pass *******/
1413 /* entries which cannot be resolved now are written into
1414 temporary structures and traversed again later */
1417 while (idx < cpcount) {
1418 /* get constant type */
1422 case CONSTANT_Class: {
1423 forward_class *nfc = DNEW(forward_class);
1425 nfc -> next = forward_classes;
1426 forward_classes = nfc;
1428 nfc -> thisindex = idx;
1429 /* reference to CONSTANT_NameAndType */
1430 nfc -> name_index = suck_u2 ();
1436 case CONSTANT_Fieldref:
1437 case CONSTANT_Methodref:
1438 case CONSTANT_InterfaceMethodref: {
1439 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1441 nff -> next = forward_fieldmethints;
1442 forward_fieldmethints = nff;
1444 nff -> thisindex = idx;
1447 /* class or interface type that contains the declaration of the field or method */
1448 nff -> class_index = suck_u2 ();
1449 /* name and descriptor of the field or method */
1450 nff -> nameandtype_index = suck_u2 ();
1456 case CONSTANT_String: {
1457 forward_string *nfs = DNEW(forward_string);
1459 nfs->next = forward_strings;
1460 forward_strings = nfs;
1462 nfs->thisindex = idx;
1463 /* reference to CONSTANT_Utf8_info with string characters */
1464 nfs->string_index = suck_u2();
1470 case CONSTANT_NameAndType: {
1471 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1473 nfn -> next = forward_nameandtypes;
1474 forward_nameandtypes = nfn;
1476 nfn -> thisindex = idx;
1477 /* reference to CONSTANT_Utf8_info containing simple name */
1478 nfn -> name_index = suck_u2 ();
1479 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1480 nfn -> sig_index = suck_u2 ();
1486 case CONSTANT_Integer: {
1487 constant_integer *ci = NEW (constant_integer);
1490 count_const_pool_len += sizeof(constant_integer);
1493 ci -> value = suck_s4 ();
1494 cptags [idx] = CONSTANT_Integer;
1501 case CONSTANT_Float: {
1502 constant_float *cf = NEW (constant_float);
1505 count_const_pool_len += sizeof(constant_float);
1508 cf -> value = suck_float ();
1509 cptags [idx] = CONSTANT_Float;
1515 case CONSTANT_Long: {
1516 constant_long *cl = NEW(constant_long);
1519 count_const_pool_len += sizeof(constant_long);
1522 cl -> value = suck_s8 ();
1523 cptags [idx] = CONSTANT_Long;
1527 panic("Long constant exceeds constant pool");
1531 case CONSTANT_Double: {
1532 constant_double *cd = NEW(constant_double);
1535 count_const_pool_len += sizeof(constant_double);
1538 cd -> value = suck_double ();
1539 cptags [idx] = CONSTANT_Double;
1543 panic("Double constant exceeds constant pool");
1547 case CONSTANT_Utf8: {
1549 /* number of bytes in the bytes array (not string-length) */
1550 u4 length = suck_u2();
1551 cptags [idx] = CONSTANT_Utf8;
1552 /* validate the string */
1553 ASSERT_LEFT(length);
1555 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1557 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1558 panic("Invalid UTF-8 string");
1560 /* insert utf-string into the utf-symboltable */
1561 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1562 /* skip bytes of the string */
1563 skip_nbytes(length);
1569 error ("Unkown constant type: %d",(int) t);
1577 /* resolve entries in temporary structures */
1579 while (forward_classes) {
1581 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1583 if (opt_verify && !is_valid_name_utf(name))
1584 panic("Class reference with invalid name");
1586 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1587 /* retrieve class from class-table */
1588 cpinfos [forward_classes -> thisindex] = class_new (name);
1590 forward_classes = forward_classes -> next;
1594 while (forward_strings) {
1596 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1598 log_text("forward_string:");
1599 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1601 log_text("\n------------------"); */
1602 /* resolve utf-string */
1603 cptags [forward_strings -> thisindex] = CONSTANT_String;
1604 cpinfos [forward_strings -> thisindex] = text;
1606 forward_strings = forward_strings -> next;
1609 while (forward_nameandtypes) {
1610 constant_nameandtype *cn = NEW (constant_nameandtype);
1613 count_const_pool_len += sizeof(constant_nameandtype);
1616 /* resolve simple name and descriptor */
1617 cn -> name = class_getconstant
1618 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1619 cn -> descriptor = class_getconstant
1620 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1624 if (!is_valid_name_utf(cn->name))
1625 panic("NameAndType with invalid name");
1626 /* disallow referencing <clinit> among others */
1627 if (cn->name->text[0] == '<' && cn->name != utf_init)
1628 panic("NameAndType with invalid special name");
1631 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1632 cpinfos [forward_nameandtypes -> thisindex] = cn;
1634 forward_nameandtypes = forward_nameandtypes -> next;
1638 while (forward_fieldmethints) {
1639 constant_nameandtype *nat;
1640 constant_FMIref *fmi = NEW (constant_FMIref);
1643 count_const_pool_len += sizeof(constant_FMIref);
1645 /* resolve simple name and descriptor */
1646 nat = class_getconstant
1647 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1650 log_text("trying to resolve:");
1651 log_text(nat->name->text);
1652 switch(forward_fieldmethints ->tag) {
1653 case CONSTANT_Fieldref:
1654 log_text("CONSTANT_Fieldref");
1656 case CONSTANT_InterfaceMethodref:
1657 log_text("CONSTANT_InterfaceMethodref");
1659 case CONSTANT_Methodref:
1660 log_text("CONSTANT_Methodref");
1664 fmi -> class = class_getconstant
1665 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1666 fmi -> name = nat -> name;
1667 fmi -> descriptor = nat -> descriptor;
1669 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1670 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1672 switch (forward_fieldmethints -> tag) {
1673 case CONSTANT_Fieldref: /* check validity of descriptor */
1674 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1676 case CONSTANT_InterfaceMethodref:
1677 case CONSTANT_Methodref: /* check validity of descriptor */
1678 checkmethoddescriptor (fmi->descriptor);
1682 forward_fieldmethints = forward_fieldmethints -> next;
1686 /* class_showconstantpool(c); */
1688 dump_release(dumpsize);
1692 /********************** Function: class_load ***********************************
1694 Loads everything interesting about a class from the class file. The
1695 'classinfo' structure must have been allocated previously.
1697 The super class and the interfaces implemented by this class need not be
1698 loaded. The link is set later by the function 'class_link'.
1700 The loaded class is removed from the list 'unloadedclasses' and added to
1701 the list 'unlinkedclasses'.
1703 *******************************************************************************/
1705 static int class_load(classinfo *c)
1711 count_class_loads++;
1714 /* output for debugging purposes */
1716 char logtext[MAXLOGTEXT];
1717 sprintf(logtext, "Loading class: ");
1718 utf_sprint(logtext + strlen(logtext), c->name);
1722 /* load classdata, throw exception on error */
1724 if (!suck_start(c->name)) {
1725 *exceptionptr = new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
1730 /* check signature */
1731 if (suck_u4() != MAGIC)
1732 panic("Can not find class-file signature");
1738 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1739 error("File version %d.%d is not supported", (int) ma, (int) mi);
1745 c->erroneous_state = 0;
1746 c->initializing_thread = 0;
1748 c->classUsed = NOTUSED; /* not used initially CO-RT */
1752 c->flags = suck_u2();
1753 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1755 /* check ACC flags consistency */
1756 if ((c->flags & ACC_INTERFACE) != 0) {
1757 if ((c->flags & ACC_ABSTRACT) == 0) {
1758 /* We work around this because interfaces in JDK 1.1 are
1759 * not declared abstract. */
1761 c->flags |= ACC_ABSTRACT;
1762 /* panic("Interface class not declared abstract"); */
1764 if ((c->flags & (ACC_FINAL)) != 0)
1765 panic("Interface class has invalid flags");
1766 if ((c->flags & (ACC_SUPER)) != 0)
1767 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1769 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1770 panic("Class is declared both abstract and final");
1774 if (class_getconstant(c, i, CONSTANT_Class) != c) {
1775 /* char message[MAXLOGTEXT]; */
1776 /* utf_sprint(message, c->name); */
1777 /* sprintf(message + strlen(message), " (wrong name: "); */
1778 /* utf_sprint(message + strlen(message), class_getconstant(c, i, CONSTANT_Class)); */
1779 /* sprintf(message + strlen(message), ")"); */
1781 /* *exceptionptr = new_exception_message("java/lang/NoClassDefFoundError", */
1784 panic("Invalid this_class in class file");
1787 /* retrieve superclass */
1788 if ((i = suck_u2())) {
1789 c->super = class_getconstant(c, i, CONSTANT_Class);
1791 /* java.lang.Object may not have a super class. */
1792 if (c->name == utf_java_lang_Object)
1793 panic("java.lang.Object with super class");
1795 /* Interfaces must have j.l.O as super class. */
1796 if ((c->flags & ACC_INTERFACE) != 0
1797 && c->super->name != utf_java_lang_Object)
1799 panic("Interface with super class other than java.lang.Object");
1804 /* This is only allowed for java.lang.Object. */
1805 if (c->name != utf_java_lang_Object)
1806 panic("Class (not java.lang.Object) without super class");
1809 /* retrieve interfaces */
1810 c->interfacescount = suck_u2();
1811 c->interfaces = MNEW(classinfo*, c->interfacescount);
1812 for (i = 0; i < c->interfacescount; i++) {
1814 class_getconstant(c, suck_u2(), CONSTANT_Class);
1818 c->fieldscount = suck_u2();
1819 /* utf_display(c->name);
1820 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1822 c->fields = GCNEW(fieldinfo, c->fieldscount);
1823 for (i = 0; i < c->fieldscount; i++) {
1824 field_load(&(c->fields[i]), c);
1828 c->methodscount = suck_u2();
1829 c->methods = MNEW(methodinfo, c->methodscount);
1830 for (i = 0; i < c->methodscount; i++) {
1831 method_load(&(c->methods[i]), c);
1834 /* Check if all fields and methods can be uniquely
1835 * identified by (name,descriptor). */
1837 /* We use a hash table here to avoid making the
1838 * average case quadratic in # of methods, fields.
1840 static int shift = 0;
1842 u2 *next; /* for chaining colliding hash entries */
1848 /* Allocate hashtable */
1849 len = c->methodscount;
1850 if (len < c->fieldscount) len = c->fieldscount;
1852 hashtab = MNEW(u2,(hashlen + len));
1853 next = hashtab + hashlen;
1855 /* Determine bitshift (to get good hash values) */
1865 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
1866 for (i = 0; i < c->fieldscount; ++i) {
1867 fieldinfo *fi = c->fields + i;
1868 /* It's ok if we lose bits here */
1869 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1871 if ((old = hashtab[index]) != 0) {
1873 /* dolog("HASHHIT %d --> %d",index,old); */
1876 /* dolog("HASHCHECK %d",old); */
1877 if (c->fields[old].name == fi->name
1878 && c->fields[old].descriptor == fi->descriptor)
1880 dolog("Duplicate field (%d,%d):",i,old);
1881 log_utf(fi->name); log_utf(fi->descriptor);
1882 panic("Fields with same name and descriptor");
1884 } while ((old = next[old]) != 0);
1886 /* else dolog("HASHLUCKY"); */
1887 hashtab[index] = i+1;
1891 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1892 for (i = 0; i < c->methodscount; ++i) {
1893 methodinfo *mi = c->methods + i;
1894 /* It's ok if we lose bits here */
1895 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1897 if ((old = hashtab[index]) != 0) {
1899 /* dolog("HASHHIT %d --> %d",index,old); */
1902 /* dolog("HASHCHECK %d",old); */
1903 if (c->methods[old].name == mi->name
1904 && c->methods[old].descriptor == mi->descriptor)
1906 dolog("Duplicate method (%d,%d):",i,old);
1907 log_utf(mi->name); log_utf(mi->descriptor);
1908 panic("Methods with same name and descriptor");
1910 } while ((old = next[old]) != 0);
1912 /* else dolog("HASHLUCKY"); */
1913 hashtab[index] = i+1;
1916 MFREE(hashtab,u2,(hashlen + len));
1920 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1921 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1922 count_class_infos += sizeof(methodinfo) * c->methodscount;
1925 /* load variable-length attribute structures */
1926 attribute_load(suck_u2(), c);
1931 /* remove class from list of unloaded classes and
1932 add to list of unlinked classes */
1933 list_remove(&unloadedclasses, c);
1934 list_addlast(&unlinkedclasses, c);
1943 /************** internal Function: class_highestinterface ***********************
1945 Used by the function class_link to determine the amount of memory needed
1946 for the interface table.
1948 *******************************************************************************/
1950 static s4 class_highestinterface(classinfo *c)
1955 if (!(c->flags & ACC_INTERFACE)) {
1956 char logtext[MAXLOGTEXT];
1957 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1958 utf_sprint(logtext + strlen(logtext), c->name);
1959 error("%s",logtext);
1963 for (i = 0; i < c->interfacescount; i++) {
1964 s4 h2 = class_highestinterface(c->interfaces[i]);
1972 /* class_addinterface **********************************************************
1974 Is needed by class_link for adding a VTBL to a class. All interfaces
1975 implemented by ic are added as well.
1977 *******************************************************************************/
1979 static void class_addinterface (classinfo *c, classinfo *ic)
1983 vftbl *vftbl = c->vftbl;
1985 if (i >= vftbl->interfacetablelength)
1986 panic ("Inernal error: interfacetable overflow");
1987 if (vftbl->interfacetable[-i])
1990 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1991 vftbl->interfacevftbllength[i] = 1;
1992 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1993 vftbl->interfacetable[-i][0] = NULL;
1996 vftbl->interfacevftbllength[i] = ic->methodscount;
1997 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
2000 count_vftbl_len += sizeof(methodptr) *
2001 (ic->methodscount + (ic->methodscount == 0));
2004 for (j=0; j<ic->methodscount; j++) {
2007 for (m = 0; m < sc->methodscount; m++) {
2008 methodinfo *mi = &(sc->methods[m]);
2009 if (method_canoverwrite(mi, &(ic->methods[j]))) {
2010 vftbl->interfacetable[-i][j] =
2011 vftbl->table[mi->vftblindex];
2021 for (j = 0; j < ic->interfacescount; j++)
2022 class_addinterface(c, ic->interfaces[j]);
2026 /******************* Function: class_new_array *********************************
2028 This function is called by class_new to setup an array class.
2030 *******************************************************************************/
2032 void class_new_array(classinfo *c)
2034 classinfo *comp = NULL;
2038 /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
2040 /* Array classes are not loaded from classfiles. */
2041 list_remove(&unloadedclasses, c);
2043 /* Check array class name */
2044 namelen = c->name->blength;
2045 if (namelen < 2 || c->name->text[0] != '[')
2046 panic("Invalid array class name");
2048 /* Check the component type */
2049 switch (c->name->text[1]) {
2051 /* c is an array of arrays. We have to create the component class. */
2052 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
2056 /* c is an array of objects. */
2057 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2058 panic("Invalid array class name");
2059 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2063 /* Setup the array class */
2064 c->super = class_java_lang_Object;
2065 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2067 c->interfacescount = 2;
2068 c->interfaces = MNEW(classinfo*,2);
2069 c->interfaces[0] = class_java_lang_Cloneable;
2070 c->interfaces[1] = class_java_io_Serializable;
2072 c->methodscount = 1;
2073 c->methods = MNEW (methodinfo, c->methodscount);
2076 memset(clone, 0, sizeof(methodinfo));
2077 clone->flags = ACC_PUBLIC;
2078 clone->name = utf_new_char("clone");
2079 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2081 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2082 clone->monoPoly = MONO;
2084 /* XXX: field: length? */
2086 /* The array class has to be linked */
2087 list_addlast(&unlinkedclasses,c);
2090 * Array classes which are created after the other classes have been
2091 * loaded and linked are linked explicitely.
2096 loader_load(c->name); /* XXX handle errors */
2100 /****************** Function: class_link_array *********************************
2102 This function is called by class_link to create the
2103 arraydescriptor for an array class.
2105 This function returns NULL if the array cannot be linked because
2106 the component type has not been linked yet.
2108 *******************************************************************************/
2110 static arraydescriptor *class_link_array(classinfo *c)
2112 classinfo *comp = NULL;
2113 int namelen = c->name->blength;
2114 arraydescriptor *desc;
2117 /* Check the component type */
2118 switch (c->name->text[1]) {
2120 /* c is an array of arrays. */
2121 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2122 if (!comp) panic("Could not find component array class.");
2126 /* c is an array of objects. */
2127 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2128 if (!comp) panic("Could not find component class.");
2132 /* If the component type has not been linked return NULL */
2133 if (comp && !comp->linked)
2136 /* Allocate the arraydescriptor */
2137 desc = NEW(arraydescriptor);
2140 /* c is an array of references */
2141 desc->arraytype = ARRAYTYPE_OBJECT;
2142 desc->componentsize = sizeof(void*);
2143 desc->dataoffset = OFFSET(java_objectarray,data);
2145 compvftbl = comp->vftbl;
2147 panic("Component class has no vftbl");
2148 desc->componentvftbl = compvftbl;
2150 if (compvftbl->arraydesc) {
2151 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2152 if (compvftbl->arraydesc->dimension >= 255)
2153 panic("Creating array of dimension >255");
2154 desc->dimension = compvftbl->arraydesc->dimension + 1;
2155 desc->elementtype = compvftbl->arraydesc->elementtype;
2158 desc->elementvftbl = compvftbl;
2159 desc->dimension = 1;
2160 desc->elementtype = ARRAYTYPE_OBJECT;
2164 /* c is an array of a primitive type */
2165 switch (c->name->text[1]) {
2166 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2167 desc->dataoffset = OFFSET(java_booleanarray,data);
2168 desc->componentsize = sizeof(u1);
2171 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2172 desc->dataoffset = OFFSET(java_bytearray,data);
2173 desc->componentsize = sizeof(u1);
2176 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2177 desc->dataoffset = OFFSET(java_chararray,data);
2178 desc->componentsize = sizeof(u2);
2181 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2182 desc->dataoffset = OFFSET(java_doublearray,data);
2183 desc->componentsize = sizeof(double);
2186 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2187 desc->dataoffset = OFFSET(java_floatarray,data);
2188 desc->componentsize = sizeof(float);
2191 case 'I': desc->arraytype = ARRAYTYPE_INT;
2192 desc->dataoffset = OFFSET(java_intarray,data);
2193 desc->componentsize = sizeof(s4);
2196 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2197 desc->dataoffset = OFFSET(java_longarray,data);
2198 desc->componentsize = sizeof(s8);
2201 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2202 desc->dataoffset = OFFSET(java_shortarray,data);
2203 desc->componentsize = sizeof(s2);
2207 panic("Invalid array class name");
2210 desc->componentvftbl = NULL;
2211 desc->elementvftbl = NULL;
2212 desc->dimension = 1;
2213 desc->elementtype = desc->arraytype;
2220 /********************** Function: class_link ***********************************
2222 Tries to link a class. The super class and every implemented interface must
2223 already have been linked. The function calculates the length in bytes that
2224 an instance of this class requires as well as the VTBL for methods and
2227 If the class can be linked, it is removed from the list 'unlinkedclasses'
2228 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2231 Attention: If cyclical class definitions are encountered, the program gets
2232 into an infinite loop (we'll have to work that out)
2234 *******************************************************************************/
2236 void class_link(classinfo *c)
2238 s4 supervftbllength; /* vftbllegnth of super class */
2239 s4 vftbllength; /* vftbllength of current class */
2240 s4 interfacetablelength; /* interface table length */
2241 classinfo *super = c->super; /* super class */
2242 classinfo *ic, *c2; /* intermediate class variables */
2243 vftbl *v; /* vftbl of current class */
2244 s4 i; /* interface/method/field counter */
2245 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2248 /* check if all superclasses are already linked, if not put c at end of
2249 unlinked list and return. Additionally initialize class fields. */
2251 /* check interfaces */
2253 for (i = 0; i < c->interfacescount; i++) {
2254 ic = c->interfaces[i];
2256 list_remove(&unlinkedclasses, c);
2257 list_addlast(&unlinkedclasses, c);
2260 if ((ic->flags & ACC_INTERFACE) == 0) {
2261 dolog("Specified interface is not declared as interface:");
2265 panic("Specified interface is not declared as interface");
2269 /* check super class */
2271 if (super == NULL) { /* class java.lang.Object */
2273 c->classUsed = USED; /* Object class is always used CO-RT*/
2275 c->instancesize = sizeof(java_objectheader);
2277 vftbllength = supervftbllength = 0;
2279 c->finalizer = NULL;
2282 if (!super->linked) {
2283 list_remove(&unlinkedclasses, c);
2284 list_addlast(&unlinkedclasses, c);
2288 if (super->flags & ACC_INTERFACE)
2289 panic("Interface specified as super class");
2291 /* handle array classes */
2292 /* The component class must have been linked already. */
2293 if (c->name->text[0] == '[')
2294 if ((arraydesc = class_link_array(c)) == NULL) {
2295 list_remove(&unlinkedclasses, c);
2296 list_addlast(&unlinkedclasses, c);
2300 /* Don't allow extending final classes */
2301 if (super->flags & ACC_FINAL)
2302 panic("Trying to extend final class");
2304 if (c->flags & ACC_INTERFACE)
2305 c->index = interfaceindex++;
2307 c->index = super->index + 1;
2309 c->instancesize = super->instancesize;
2311 vftbllength = supervftbllength = super->vftbl->vftbllength;
2313 c->finalizer = super->finalizer;
2318 char logtext[MAXLOGTEXT];
2319 sprintf(logtext, "Linking Class: ");
2320 utf_sprint(logtext + strlen(logtext), c->name );
2324 /* compute vftbl length */
2326 for (i = 0; i < c->methodscount; i++) {
2327 methodinfo *m = &(c->methods[i]);
2329 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2330 classinfo *sc = super;
2333 for (j = 0; j < sc->methodscount; j++) {
2334 if (method_canoverwrite(m, &(sc->methods[j]))) {
2335 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2336 goto notfoundvftblindex;
2337 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2340 log_utf(sc->methods[j].name);
2341 log_utf(sc->methods[j].descriptor);
2342 panic("Trying to overwrite final method");
2344 m->vftblindex = sc->methods[j].vftblindex;
2345 goto foundvftblindex;
2351 m->vftblindex = (vftbllength++);
2357 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2360 /* compute interfacetable length */
2362 interfacetablelength = 0;
2365 for (i = 0; i < c2->interfacescount; i++) {
2366 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2367 if (h > interfacetablelength)
2368 interfacetablelength = h;
2373 /* allocate virtual function table */
2375 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2376 (vftbllength - 1) + sizeof(methodptr*) *
2377 (interfacetablelength - (interfacetablelength > 0)));
2378 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2379 (interfacetablelength > 1));
2380 c->header.vftbl = c->vftbl = v;
2382 v->vftbllength = vftbllength;
2383 v->interfacetablelength = interfacetablelength;
2384 v->arraydesc = arraydesc;
2386 /* store interface index in vftbl */
2387 if (c->flags & ACC_INTERFACE)
2388 v->baseval = -(c->index);
2390 /* copy virtual function table of super class */
2392 for (i = 0; i < supervftbllength; i++)
2393 v->table[i] = super->vftbl->table[i];
2395 /* add method stubs into virtual function table */
2397 for (i = 0; i < c->methodscount; i++) {
2398 methodinfo *m = &(c->methods[i]);
2399 if (!(m->flags & ACC_STATIC)) {
2400 v->table[m->vftblindex] = m->stubroutine;
2404 /* compute instance size and offset of each field */
2406 for (i = 0; i < c->fieldscount; i++) {
2408 fieldinfo *f = &(c->fields[i]);
2410 if (!(f->flags & ACC_STATIC) ) {
2411 dsize = desc_typesize(f->descriptor);
2412 c->instancesize = ALIGN(c->instancesize, dsize);
2413 f->offset = c->instancesize;
2414 c->instancesize += dsize;
2418 /* initialize interfacetable and interfacevftbllength */
2420 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2423 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2426 for (i = 0; i < interfacetablelength; i++) {
2427 v->interfacevftbllength[i] = 0;
2428 v->interfacetable[-i] = NULL;
2431 /* add interfaces */
2433 for (c2 = c; c2 != NULL; c2 = c2->super)
2434 for (i = 0; i < c2->interfacescount; i++) {
2435 class_addinterface(c, c2->interfaces[i]);
2438 /* add finalizer method (not for java.lang.Object) */
2440 if (super != NULL) {
2442 static utf *finame = NULL;
2443 static utf *fidesc = NULL;
2446 finame = utf_finalize;
2448 fidesc = utf_fidesc;
2450 fi = class_findmethod(c, finame, fidesc);
2452 if (!(fi->flags & ACC_STATIC)) {
2462 list_remove(&unlinkedclasses, c);
2463 list_addlast(&linkedclasses, c);
2467 /******************* Function: class_freepool **********************************
2469 Frees all resources used by this classes Constant Pool.
2471 *******************************************************************************/
2473 static void class_freecpool (classinfo *c)
2479 for (idx=0; idx < c->cpcount; idx++) {
2480 tag = c->cptags[idx];
2481 info = c->cpinfos[idx];
2485 case CONSTANT_Fieldref:
2486 case CONSTANT_Methodref:
2487 case CONSTANT_InterfaceMethodref:
2488 FREE (info, constant_FMIref);
2490 case CONSTANT_Integer:
2491 FREE (info, constant_integer);
2493 case CONSTANT_Float:
2494 FREE (info, constant_float);
2497 FREE (info, constant_long);
2499 case CONSTANT_Double:
2500 FREE (info, constant_double);
2502 case CONSTANT_NameAndType:
2503 FREE (info, constant_nameandtype);
2509 MFREE (c -> cptags, u1, c -> cpcount);
2510 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2514 /*********************** Function: class_free **********************************
2516 Frees all resources used by the class.
2518 *******************************************************************************/
2520 static void class_free(classinfo *c)
2527 MFREE(c->interfaces, classinfo*, c->interfacescount);
2529 for (i = 0; i < c->fieldscount; i++)
2530 field_free(&(c->fields[i]));
2532 for (i = 0; i < c->methodscount; i++)
2533 method_free(&(c->methods[i]));
2534 MFREE(c->methods, methodinfo, c->methodscount);
2536 if ((v = c->vftbl) != NULL) {
2538 mem_free(v->arraydesc,sizeof(arraydescriptor));
2540 for (i = 0; i < v->interfacetablelength; i++) {
2541 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2543 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2545 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2546 sizeof(methodptr*) * (v->interfacetablelength -
2547 (v->interfacetablelength > 0));
2548 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2549 (v->interfacetablelength > 1));
2553 if (c->innerclasscount)
2554 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2556 /* if (c->classvftbl)
2557 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2563 /************************* Function: class_findfield ***************************
2565 Searches a 'classinfo' structure for a field having the given name and
2568 *******************************************************************************/
2570 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2574 for (i = 0; i < c->fieldscount; i++) {
2575 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2576 return &(c->fields[i]);
2579 panic("Can not find field given in CONSTANT_Fieldref");
2581 /* keep compiler happy */
2586 /****************** Function: class_resolvefield_int ***************************
2588 This is an internally used helper function. Do not use this directly.
2590 Tries to resolve a field having the given name and type.
2591 If the field cannot be resolved, NULL is returned.
2593 *******************************************************************************/
2596 fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2601 /* search for field in class c */
2602 for (i = 0; i < c->fieldscount; i++) {
2603 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2604 return &(c->fields[i]);
2607 /* try superinterfaces recursively */
2608 for (i=0; i<c->interfacescount; ++i) {
2609 fi = class_resolvefield_int(c->interfaces[i],name,desc);
2614 /* try superclass */
2616 return class_resolvefield_int(c->super,name,desc);
2623 /********************* Function: class_resolvefield ***************************
2625 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2626 If the field cannot be resolved this function panics.
2628 *******************************************************************************/
2630 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2635 /* XXX resolve class c */
2636 /* XXX check access from REFERER to C */
2638 fi = class_resolvefield_int(c,name,desc);
2644 panic("Cannot find field given in CONSTANT_Fieldref");
2645 /* XXX should throw NoSuchFieldError */
2648 /* XXX check access rights */
2654 /************************* Function: class_findmethod **************************
2656 Searches a 'classinfo' structure for a method having the given name and
2657 type and returns the index in the class info structure.
2658 If type is NULL, it is ignored.
2660 *******************************************************************************/
2662 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2665 //#define JOWENN_DEBUG1
2666 //#define JOWENN_DEBUG2
2667 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2669 int buffer_len, pos;
2672 #ifdef JOWENN_DEBUG1
2675 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2677 buffer = MNEW(char, buffer_len);
2679 strcpy(buffer, "class_findmethod: method:");
2680 utf_sprint(buffer + strlen(buffer), name);
2681 strcpy(buffer + strlen(buffer), ", desc: ");
2682 utf_sprint(buffer + strlen(buffer), desc);
2683 strcpy(buffer + strlen(buffer), ", classname: ");
2684 utf_sprint(buffer + strlen(buffer), c->name);
2688 MFREE(buffer, char, buffer_len);
2690 for (i = 0; i < c->methodscount; i++) {
2691 #ifdef JOWENN_DEBUG2
2693 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2695 buffer = MNEW(char, buffer_len);
2697 strcpy(buffer, "class_findmethod: comparing to method:");
2698 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2699 strcpy(buffer + strlen(buffer), ", desc: ");
2700 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2704 MFREE(buffer, char, buffer_len);
2708 if ((c->methods[i].name == name) && ((desc == NULL) ||
2709 (c->methods[i].descriptor == desc))) {
2714 #ifdef JOWENN_DEBUG2
2715 class_showconstantpool(c);
2716 log_text("class_findmethod: returning NULL");
2723 /************************* Function: class_findmethod **************************
2725 Searches a 'classinfo' structure for a method having the given name and
2727 If type is NULL, it is ignored.
2729 *******************************************************************************/
2731 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2735 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2737 int buffer_len, pos;
2739 #ifdef JOWENN_DEBUG1
2742 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2744 buffer = MNEW(char, buffer_len);
2746 strcpy(buffer, "class_findmethod: method:");
2747 utf_sprint(buffer + strlen(buffer), name);
2748 strcpy(buffer + strlen(buffer), ", desc: ");
2749 utf_sprint(buffer + strlen(buffer), desc);
2750 strcpy(buffer + strlen(buffer), ", classname: ");
2751 utf_sprint(buffer + strlen(buffer), c->name);
2755 MFREE(buffer, char, buffer_len);
2757 for (i = 0; i < c->methodscount; i++) {
2758 #ifdef JOWENN_DEBUG2
2760 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2762 buffer = MNEW(char, buffer_len);
2764 strcpy(buffer, "class_findmethod: comparing to method:");
2765 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2766 strcpy(buffer + strlen(buffer), ", desc: ");
2767 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2771 MFREE(buffer, char, buffer_len);
2774 if ((c->methods[i].name == name) && ((desc == NULL) ||
2775 (c->methods[i].descriptor == desc))) {
2776 return &(c->methods[i]);
2779 #ifdef JOWENN_DEBUG2
2780 class_showconstantpool(c);
2781 log_text("class_findmethod: returning NULL");
2786 s4 idx=class_findmethodIndex(c, name, desc);
2787 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2788 if (idx == -1) return NULL;
2790 return &(c->methods[idx]);
2794 /*********************** Function: class_fetchmethod **************************
2796 like class_findmethod, but aborts with an error if the method is not found
2798 *******************************************************************************/
2800 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2803 mi = class_findmethod(c, name, desc);
2806 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2807 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2808 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2809 panic("Method not found");
2816 /*********************** Function: class_findmethod_w**************************
2818 like class_findmethod, but logs a warning if the method is not found
2820 *******************************************************************************/
2822 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2825 mi = class_findmethod(c, name, desc);
2828 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2829 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2830 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2832 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2833 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2834 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2835 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2836 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2837 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2838 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2839 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2840 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2841 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2842 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2845 log_plain(" : WARNING: Method not found");log_nl( );
2852 /************************* Function: class_findmethod_approx ******************
2854 like class_findmethod but ignores the return value when comparing the
2857 *******************************************************************************/
2859 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2863 for (i = 0; i < c->methodscount; i++) {
2864 if (c->methods[i].name == name) {
2865 utf *meth_descr = c->methods[i].descriptor;
2869 return &(c->methods[i]);
2871 if (desc->blength <= meth_descr->blength) {
2872 /* current position in utf text */
2873 char *desc_utf_ptr = desc->text;
2874 char *meth_utf_ptr = meth_descr->text;
2875 /* points behind utf strings */
2876 char *desc_end = utf_end(desc);
2877 char *meth_end = utf_end(meth_descr);
2880 /* compare argument types */
2881 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2883 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2884 break; /* no match */
2887 return &(c->methods[i]); /* all parameter types equal */
2897 /***************** Function: class_resolvemethod_approx ***********************
2899 Searches a class and every super class for a method (without paying
2900 attention to the return value)
2902 *******************************************************************************/
2904 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2907 /* search for method (ignore returntype) */
2908 methodinfo *m = class_findmethod_approx(c, name, desc);
2911 /* search superclass */
2919 /************************* Function: class_resolvemethod ***********************
2921 Searches a class and every super class for a method.
2923 *******************************************************************************/
2925 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2928 methodinfo *m = class_findmethod(c, name, desc);
2930 /* search superclass */
2938 /****************** Function: class_resolveinterfacemethod_int ****************
2940 Internally used helper function. Do not use this directly.
2942 *******************************************************************************/
2945 methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
2950 mi = class_findmethod(c,name,desc);
2954 /* try the superinterfaces */
2955 for (i=0; i<c->interfacescount; ++i) {
2956 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
2964 /******************** Function: class_resolveinterfacemethod ******************
2966 Resolves a reference from REFERER to a method with NAME and DESC in
2969 *******************************************************************************/
2971 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2976 /* XXX resolve class c */
2977 /* XXX check access from REFERER to C */
2979 if ((c->flags & ACC_INTERFACE) == 0)
2980 return NULL; /* should throw IncompatibleClassChangeError */
2982 mi = class_resolveinterfacemethod_int(c,name,desc);
2986 /* try class java.lang.Object */
2987 mi = class_findmethod(class_java_lang_Object,name,desc);
2991 return NULL; /* should throw NoSuchMethodError */
2997 /********************* Function: class_resolveclassmethod *********************
2999 Resolves a reference from REFERER to a method with NAME and DESC in
3002 *******************************************************************************/
3004 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3011 /* XXX resolve class c */
3012 /* XXX check access from REFERER to C */
3014 if ((c->flags & ACC_INTERFACE) != 0)
3015 return NULL; /* should throw IncompatibleClassChangeError */
3017 /* try class c and its superclasses */
3020 mi = class_findmethod(cls,name,desc);
3023 } while ((cls = cls->super) != NULL); /* try the superclass */
3025 /* try the superinterfaces */
3026 for (i=0; i<c->interfacescount; ++i) {
3027 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3032 return NULL; /* should throw NoSuchMethodError */
3035 if ((mi->flags & ACC_ABSTRACT) != 0 &&
3036 (c->flags & ACC_ABSTRACT) == 0)
3037 return NULL; /* should throw AbstractMethodError */
3039 /* XXX check access rights */
3045 /************************* Function: class_issubclass **************************
3047 Checks if sub is a descendant of super.
3049 *******************************************************************************/
3051 bool class_issubclass(classinfo *sub, classinfo *super)
3054 if (!sub) return false;
3055 if (sub == super) return true;
3061 /****************** Initialization function for classes ******************
3063 In Java, every class can have a static initialization function. This
3064 function has to be called BEFORE calling other methods or accessing static
3067 *******************************************************************************/
3069 void class_init(classinfo *c)
3073 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3077 if (!makeinitializations)
3082 c->initialized = true;
3085 count_class_inits++;
3088 /* initialize super class */
3091 char logtext[MAXLOGTEXT];
3092 sprintf(logtext, "Initialize super class ");
3093 utf_sprint(logtext + strlen(logtext), c->super->name);
3094 sprintf(logtext + strlen(logtext), " from ");
3095 utf_sprint(logtext + strlen(logtext), c->name);
3098 class_init(c->super);
3101 /* initialize interface classes */
3102 for (i = 0; i < c->interfacescount; i++) {
3104 char logtext[MAXLOGTEXT];
3105 sprintf(logtext, "Initialize interface class ");
3106 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
3107 sprintf(logtext + strlen(logtext), " from ");
3108 utf_sprint(logtext + strlen(logtext), c->name);
3111 class_init(c->interfaces[i]); /* real */
3114 m = class_findmethod(c, utf_clinit, utf_fidesc);
3117 char logtext[MAXLOGTEXT];
3118 sprintf(logtext, "Class ");
3119 utf_sprint(logtext + strlen(logtext), c->name);
3120 sprintf(logtext + strlen(logtext), " has no initializer");
3123 /* goto callinitialize;*/
3127 if (!(m->flags & ACC_STATIC))
3128 panic("Class initializer is not static!");
3131 char logtext[MAXLOGTEXT];
3132 sprintf(logtext, "Starting initializer for class: ");
3133 utf_sprint(logtext + strlen(logtext), c->name);
3137 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3142 /* now call the initializer */
3143 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3145 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3146 assert(blockInts == 0);
3150 /* we have to throw an exception */
3151 if (*exceptionptr) {
3152 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
3153 printf("Caused by: ");
3154 utf_display((*exceptionptr)->vftbl->class->name);
3156 /* do we have a detail message? */
3157 if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
3159 utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
3168 char logtext[MAXLOGTEXT];
3169 sprintf(logtext, "Finished initializer for class: ");
3170 utf_sprint(logtext + strlen(logtext), c->name);
3174 if (c->name == utf_systemclass) {
3175 /* class java.lang.System requires explicit initialization */
3178 printf("#### Initializing class System");
3180 /* find initializing method */
3181 m = class_findmethod(c,
3182 utf_initsystemclass,
3186 /* no method found */
3187 /* printf("initializeSystemClass failed"); */
3191 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3196 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3198 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3199 assert(blockInts == 0);
3203 if (*exceptionptr) {
3204 printf("#### initializeSystemClass has thrown: ");
3205 utf_display((*exceptionptr)->vftbl->class->name);
3213 /********* Function: find_class_method_constant *********/
3215 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3220 for (i=0; i<c->cpcount; i++) {
3222 e = c -> cpinfos [i];
3225 switch (c -> cptags [i]) {
3226 case CONSTANT_Methodref:
3228 constant_FMIref *fmi = e;
3229 if ( (fmi->class->name == c1)
3230 && (fmi->name == m1)
3231 && (fmi->descriptor == d1)) {
3238 case CONSTANT_InterfaceMethodref:
3240 constant_FMIref *fmi = e;
3241 if ( (fmi->class->name == c1)
3242 && (fmi->name == m1)
3243 && (fmi->descriptor == d1)) {
3257 void class_showconstanti(classinfo *c, int ii)
3263 printf ("#%d: ", (int) i);
3265 switch (c->cptags [i]) {
3266 case CONSTANT_Class:
3267 printf("Classreference -> ");
3268 utf_display(((classinfo*)e)->name);
3271 case CONSTANT_Fieldref:
3272 printf("Fieldref -> "); goto displayFMIi;
3273 case CONSTANT_Methodref:
3274 printf("Methodref -> "); goto displayFMIi;
3275 case CONSTANT_InterfaceMethodref:
3276 printf("InterfaceMethod -> "); goto displayFMIi;
3279 constant_FMIref *fmi = e;
3280 utf_display(fmi->class->name);
3282 utf_display(fmi->name);
3284 utf_display(fmi->descriptor);
3288 case CONSTANT_String:
3289 printf("String -> ");
3292 case CONSTANT_Integer:
3293 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3295 case CONSTANT_Float:
3296 printf("Float -> %f", ((constant_float*)e)->value);
3298 case CONSTANT_Double:
3299 printf("Double -> %f", ((constant_double*)e)->value);
3303 u8 v = ((constant_long*)e)->value;
3305 printf("Long -> %ld", (long int) v);
3307 printf("Long -> HI: %ld, LO: %ld\n",
3308 (long int) v.high, (long int) v.low);
3312 case CONSTANT_NameAndType:
3314 constant_nameandtype *cnt = e;
3315 printf("NameAndType: ");
3316 utf_display(cnt->name);
3318 utf_display(cnt->descriptor);
3326 panic("Invalid type of ConstantPool-Entry");
3333 void class_showconstantpool (classinfo *c)
3338 printf ("---- dump of constant pool ----\n");
3340 for (i=0; i<c->cpcount; i++) {
3341 printf ("#%d: ", (int) i);
3343 e = c -> cpinfos [i];
3346 switch (c -> cptags [i]) {
3347 case CONSTANT_Class:
3348 printf ("Classreference -> ");
3349 utf_display ( ((classinfo*)e) -> name );
3352 case CONSTANT_Fieldref:
3353 printf ("Fieldref -> "); goto displayFMI;
3354 case CONSTANT_Methodref:
3355 printf ("Methodref -> "); goto displayFMI;
3356 case CONSTANT_InterfaceMethodref:
3357 printf ("InterfaceMethod -> "); goto displayFMI;
3360 constant_FMIref *fmi = e;
3361 utf_display ( fmi->class->name );
3363 utf_display ( fmi->name);
3365 utf_display ( fmi->descriptor );
3369 case CONSTANT_String:
3370 printf ("String -> ");
3373 case CONSTANT_Integer:
3374 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3376 case CONSTANT_Float:
3377 printf ("Float -> %f", ((constant_float*)e) -> value);
3379 case CONSTANT_Double:
3380 printf ("Double -> %f", ((constant_double*)e) -> value);
3384 u8 v = ((constant_long*)e) -> value;
3386 printf ("Long -> %ld", (long int) v);
3388 printf ("Long -> HI: %ld, LO: %ld\n",
3389 (long int) v.high, (long int) v.low);
3393 case CONSTANT_NameAndType:
3395 constant_nameandtype *cnt = e;
3396 printf ("NameAndType: ");
3397 utf_display (cnt->name);
3399 utf_display (cnt->descriptor);
3403 printf ("Utf8 -> ");
3407 panic ("Invalid type of ConstantPool-Entry");
3417 /********** Function: class_showmethods (debugging only) *************/
3419 void class_showmethods (classinfo *c)
3423 printf ("--------- Fields and Methods ----------------\n");
3424 printf ("Flags: "); printflags (c->flags); printf ("\n");
3426 printf ("This: "); utf_display (c->name); printf ("\n");
3428 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3430 printf ("Index: %d\n", c->index);
3432 printf ("interfaces:\n");
3433 for (i=0; i < c-> interfacescount; i++) {
3435 utf_display (c -> interfaces[i] -> name);
3436 printf (" (%d)\n", c->interfaces[i] -> index);
3439 printf ("fields:\n");
3440 for (i=0; i < c -> fieldscount; i++) {
3441 field_display (&(c -> fields[i]));
3444 printf ("methods:\n");
3445 for (i=0; i < c -> methodscount; i++) {
3446 methodinfo *m = &(c->methods[i]);
3447 if ( !(m->flags & ACC_STATIC))
3448 printf ("vftblindex: %d ", m->vftblindex);
3450 method_display ( m );
3454 printf ("Virtual function table:\n");
3455 for (i=0; i<c->vftbl->vftbllength; i++) {
3456 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3463 /******************************************************************************/
3464 /******************* General functions for the class loader *******************/
3465 /******************************************************************************/
3467 /********************* Function: loader_load ***********************************
3469 Loads and links the class desired class and each class and interface
3471 Returns: a pointer to this class
3473 *******************************************************************************/
3475 static int loader_load_running = 0;
3477 classinfo *loader_load(utf *topname)
3483 classinfo *notlinkable;
3485 /* avoid recursive calls */
3486 if (loader_load_running)
3487 return class_new(topname);
3489 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3493 loader_load_running++;
3495 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3500 starttime = getcputime();
3502 top = class_new(topname);
3505 while ((c = list_first(&unloadedclasses))) {
3506 if (!class_load(c)) {
3508 dolog("Failed to load class");
3509 list_remove(&unloadedclasses, c);
3516 dolog("Linking...");
3518 /* Added a hack to break infinite linking loops. A better
3519 * linking algorithm would be nice. -Edwin */
3521 while ((c = list_first(&unlinkedclasses))) {
3526 else if (notlinkable == c) {
3527 /* We tried to link this class for the second time and
3528 * no other classes were linked in between, so we are
3532 dolog("Cannot resolve linking dependencies");
3536 *exceptionptr = new_exception_utfmessage(string_java_lang_LinkageError,
3545 dolog("Linking done.");
3548 loader_compute_subclasses();
3551 if (getloadingtime) {
3552 stoptime = getcputime();
3553 loadingtime += (stoptime - starttime);
3557 loader_load_running--;
3559 /* check if a former loader_load call tried to load/link the class and
3560 failed. This is needed because the class didn't appear in the
3561 undloadclasses or unlinkedclasses list during this class. */
3565 dolog("Failed to load class (former call)");
3567 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
3571 } else if (!top->linked) {
3573 dolog("Failed to link class (former call)");
3575 new_exception_utfmessage(string_java_lang_LinkageError,
3581 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3585 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3589 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3595 /****************** Function: loader_load_sysclass ****************************
3597 Loads and links the class desired class and each class and interface
3600 The pointer to the classinfo is stored in *top if top != NULL.
3601 The pointer is also returned.
3603 If the class could not be loaded the function aborts with an error.
3605 *******************************************************************************/
3607 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3611 if ((cls = loader_load(topname)) == NULL) {
3612 log_plain("Could not load important system class: ");
3613 log_plain_utf(topname);
3615 panic("Could not load important system class");
3618 if (top) *top = cls;
3624 /**************** function: create_primitive_classes ***************************
3626 create classes representing primitive types
3628 ********************************************************************************/
3630 void create_primitive_classes()
3634 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3635 /* create primitive class */
3636 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3637 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3638 c -> impldBy = NULL;
3640 /* prevent loader from loading primitive class */
3641 list_remove (&unloadedclasses, c);
3643 /* add to unlinked classes */
3644 list_addlast (&unlinkedclasses, c);
3645 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3648 primitivetype_table[i].class_primitive = c;
3650 /* create class for wrapping the primitive type */
3651 primitivetype_table[i].class_wrap =
3652 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3653 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3654 primitivetype_table[i].class_wrap -> impldBy = NULL;
3656 /* create the primitive array class */
3657 if (primitivetype_table[i].arrayname) {
3658 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3659 primitivetype_table[i].arrayclass = c;
3661 if (!c->linked) class_link(c);
3662 primitivetype_table[i].arrayvftbl = c->vftbl;
3667 /**************** function: class_primitive_from_sig ***************************
3669 return the primitive class indicated by the given signature character
3671 If the descriptor does not indicate a valid primitive type the
3672 return value is NULL.
3674 ********************************************************************************/
3676 classinfo *class_primitive_from_sig(char sig)
3679 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3680 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3681 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3682 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3683 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3684 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3685 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3686 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3687 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3692 /****************** function: class_from_descriptor ****************************
3694 return the class indicated by the given descriptor
3696 utf_ptr....first character of descriptor
3697 end_ptr....first character after the end of the string
3698 next.......if non-NULL, *next is set to the first character after
3699 the descriptor. (Undefined if an error occurs.)
3701 mode.......a combination (binary or) of the following flags:
3703 (Flags marked with * are the default settings.)
3705 What to do if a reference type descriptor is parsed successfully:
3707 CLASSLOAD_SKIP...skip it and return something != NULL
3708 * CLASSLOAD_NEW....get classinfo * via class_new
3709 CLASSLOAD_LOAD...get classinfo * via loader_load
3711 How to handle primitive types:
3713 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3714 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3716 How to handle "V" descriptors:
3718 * CLASSLOAD_VOID.....handle it like other primitive types
3719 CLASSLOAD_NOVOID...treat it as an error
3721 How to deal with extra characters after the end of the
3724 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3725 CLASSLOAD_CHECKEND.....treat them as an error
3727 How to deal with errors:
3729 * CLASSLOAD_PANIC....abort execution with an error message
3730 CLASSLOAD_NOPANIC..return NULL on error
3732 ********************************************************************************/
3734 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3735 char **next, int mode)
3737 char *start = utf_ptr;
3741 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3743 if (mode & CLASSLOAD_CHECKEND)
3744 error |= (utf_ptr != end_ptr);
3747 if (next) *next = utf_ptr;
3751 if (mode & CLASSLOAD_NOVOID)
3762 return (mode & CLASSLOAD_NULLPRIMITIVE)
3764 : class_primitive_from_sig(*start);
3771 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3772 name = utf_new(start, utf_ptr - start);
3773 return (mode & CLASSLOAD_LOAD)
3774 ? loader_load(name) : class_new(name); /* XXX handle errors */
3778 /* An error occurred */
3779 if (mode & CLASSLOAD_NOPANIC)
3782 log_plain("Invalid descriptor at beginning of '");
3783 log_plain_utf(utf_new(start, end_ptr - start));
3787 panic("Invalid descriptor");
3789 /* keep compiler happy */
3794 /******************* function: type_from_descriptor ****************************
3796 return the basic type indicated by the given descriptor
3798 This function parses a descriptor and returns its basic type as
3799 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3801 cls...if non-NULL the referenced variable is set to the classinfo *
3802 returned by class_from_descriptor.
3804 For documentation of the arguments utf_ptr, end_ptr, next and mode
3805 see class_from_descriptor. The only difference is that
3806 type_from_descriptor always uses CLASSLOAD_PANIC.
3808 ********************************************************************************/
3810 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3811 char **next, int mode)
3814 if (!cls) cls = &mycls;
3815 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3832 return TYPE_ADDRESS;
3836 /*************** function: create_pseudo_classes *******************************
3838 create pseudo classes used by the typechecker
3840 ********************************************************************************/
3842 static void create_pseudo_classes()
3844 /* pseudo class for Arraystubs (extends java.lang.Object) */
3846 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3847 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3849 pseudo_class_Arraystub->super = class_java_lang_Object;
3850 pseudo_class_Arraystub->interfacescount = 2;
3851 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3852 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3853 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3855 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3856 class_link(pseudo_class_Arraystub);
3858 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3860 /* pseudo class representing the null type */
3862 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3863 list_remove(&unloadedclasses, pseudo_class_Null);
3865 pseudo_class_Null->super = class_java_lang_Object;
3867 list_addlast(&unlinkedclasses, pseudo_class_Null);
3868 class_link(pseudo_class_Null);
3870 /* pseudo class representing new uninitialized objects */
3872 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3873 list_remove(&unloadedclasses, pseudo_class_New);
3875 pseudo_class_New->super = class_java_lang_Object;
3877 list_addlast(&unlinkedclasses, pseudo_class_New);
3878 class_link(pseudo_class_New);
3882 /********************** Function: loader_init **********************************
3884 Initializes all lists and loads all classes required for the system or the
3887 *******************************************************************************/
3889 void loader_init(u1 *stackbottom)
3893 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3894 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3895 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3897 /* create utf-symbols for pointer comparison of frequently used strings */
3898 utf_innerclasses = utf_new_char("InnerClasses");
3899 utf_constantvalue = utf_new_char("ConstantValue");
3900 utf_code = utf_new_char("Code");
3901 utf_exceptions = utf_new_char("Exceptions");
3902 utf_linenumbertable = utf_new_char("LineNumberTable");
3903 utf_sourcefile = utf_new_char("SourceFile");
3904 utf_finalize = utf_new_char("finalize");
3905 utf_fidesc = utf_new_char("()V");
3906 utf_init = utf_new_char("<init>");
3907 utf_clinit = utf_new_char("<clinit>");
3908 utf_initsystemclass = utf_new_char("initializeSystemClass");
3909 utf_systemclass = utf_new_char("java/lang/System");
3910 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3911 utf_initialize = utf_new_char("initialize");
3912 utf_initializedesc = utf_new_char("(I)V");
3914 utf_vmclass = utf_new_char("java/lang/VMClass");
3915 utf_java_lang_Object= utf_new_char("java/lang/Object");
3917 array_packagename = utf_new_char("<the array package>");
3919 /* create some important classes */
3920 /* These classes have to be created now because the classinfo
3921 * pointers are used in the loading code.
3923 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3924 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3925 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3926 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3928 if (verbose) log_text("loader_init: java/lang/Object");
3929 /* load the classes which were created above */
3930 loader_load_sysclass(NULL, class_java_lang_Object->name);
3932 loader_inited = 1; /*JOWENN*/
3934 loader_load_sysclass(&class_java_lang_Throwable,
3935 utf_new_char("java/lang/Throwable"));
3937 /* create classes representing primitive types */
3938 create_primitive_classes();
3940 /* create classes used by the typechecker */
3941 create_pseudo_classes();
3943 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3944 stringtable_update();
3946 #if defined(USE_THREADS)
3955 /********************* Function: loader_initclasses ****************************
3957 Initializes all loaded but uninitialized classes
3959 *******************************************************************************/
3962 /* XXX TWISTI: i think we do not need this */
3963 void loader_initclasses ()
3967 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3968 pthread_mutex_lock(&compiler_mutex);
3971 intsDisable(); /* schani */
3973 if (makeinitializations) {
3974 c = list_first(&linkedclasses);
3977 c = list_next(&linkedclasses, c);
3981 intsRestore(); /* schani */
3983 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3984 pthread_mutex_unlock(&compiler_mutex);
3990 static void loader_compute_class_values(classinfo *c)
3994 c->vftbl->baseval = ++classvalue;
3997 while (subs != NULL) {
3998 loader_compute_class_values(subs);
3999 subs = subs->nextsub;
4001 c->vftbl->diffval = classvalue - c->vftbl->baseval;
4006 for (i = 0; i < c->index; i++)
4008 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
4009 utf_display(c->name);
4016 void loader_compute_subclasses()
4020 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4021 intsDisable(); /* schani */
4024 c = list_first(&linkedclasses);
4026 if (!(c->flags & ACC_INTERFACE)) {
4030 c = list_next(&linkedclasses, c);
4033 c = list_first(&linkedclasses);
4035 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4036 c->nextsub = c->super->sub;
4039 c = list_next(&linkedclasses, c);
4043 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4046 loader_compute_class_values(class_java_lang_Object);
4047 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4051 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4052 intsRestore(); /* schani */
4057 /******************** function classloader_buffer ******************************
4059 sets buffer for reading classdata
4061 *******************************************************************************/
4063 void classload_buffer(u1 *buf, int len)
4066 classbuffer_size = len;
4067 classbuf_pos = buf - 1;
4071 /******************** Function: loader_close ***********************************
4075 *******************************************************************************/
4081 while ((c = list_first(&unloadedclasses))) {
4082 list_remove(&unloadedclasses, c);
4083 /* class_free(c); */
4085 while ((c = list_first(&unlinkedclasses))) {
4086 list_remove(&unlinkedclasses, c);
4087 /* class_free(c); */
4089 while ((c = list_first(&linkedclasses))) {
4090 list_remove(&linkedclasses, c);
4091 /* class_free(c); */
4097 * These are local overrides for various environment variables in Emacs.
4098 * Please do not remove this and leave it at the end of the file, where
4099 * Emacs will automagically detect them.
4100 * ---------------------------------------------------------------------
4103 * indent-tabs-mode: t