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 916 2004-02-08 15:17:10Z edwin $
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
64 /* global variables ***********************************************************/
66 int count_class_infos = 0; /* variables for measurements */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
75 static s4 interfaceindex; /* sequential numbering of interfaces */
78 list unloadedclasses; /* list of all referenced but not loaded classes */
79 list unlinkedclasses; /* list of all loaded but not linked classes */
80 list linkedclasses; /* list of all completely linked classes */
83 /* utf-symbols for pointer comparison of frequently used strings */
85 static utf *utf_innerclasses; /* InnerClasses */
86 static utf *utf_constantvalue; /* ConstantValue */
87 static utf *utf_code; /* Code */
88 static utf *utf_finalize; /* finalize */
89 static utf *utf_fidesc; /* ()V changed */
90 static utf *utf_init; /* <init> */
91 static utf *utf_clinit; /* <clinit> */
92 static utf *utf_initsystemclass; /* initializeSystemClass */
93 static utf *utf_systemclass; /* java/lang/System */
94 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
95 static utf *utf_vmclass; /* java/lang/VMClassLoader */
96 static utf *utf_initialize;
97 static utf *utf_initializedesc;
98 static utf *utf_java_lang_Object; /* java/lang/Object */
111 /* important system classes ***************************************************/
113 classinfo *class_java_lang_Object;
114 classinfo *class_java_lang_String;
116 classinfo *class_java_lang_Throwable;
117 classinfo *class_java_lang_Cloneable;
118 classinfo *class_java_io_Serializable;
120 /* Pseudo classes for the typechecker */
121 classinfo *pseudo_class_Arraystub = NULL;
122 classinfo *pseudo_class_Null = NULL;
123 classinfo *pseudo_class_New = NULL;
124 vftbl *pseudo_class_Arraystub_vftbl = NULL;
127 /* These are made static so they cannot be used for throwing in native */
129 static classinfo *class_java_lang_ClassCastException;
130 static classinfo *class_java_lang_NullPointerException;
131 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
132 static classinfo *class_java_lang_NegativeArraySizeException;
133 static classinfo *class_java_lang_OutOfMemoryError;
134 static classinfo *class_java_lang_ArithmeticException;
135 static classinfo *class_java_lang_ArrayStoreException;
136 static classinfo *class_java_lang_ThreadDeath;
138 utf *array_packagename = NULL;
140 static int loader_inited = 0;
143 /********************************************************************
144 list of classpath entries (either filesystem directories or
146 ********************************************************************/
147 static classpath_info *classpath_entries=0;
150 /******************************************************************************
152 structure for primitive classes: contains the class for wrapping the
153 primitive type, the primitive class, the name of the class for wrapping,
154 the one character type signature and the name of the primitive class
156 ******************************************************************************/
158 /* CAUTION: Don't change the order of the types. This table is indexed
159 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
161 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
162 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
163 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
164 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
165 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
166 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
167 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
168 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
169 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
170 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
174 /* instances of important system classes **************************************/
176 java_objectheader *proto_java_lang_ClassCastException;
177 java_objectheader *proto_java_lang_NullPointerException;
178 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
179 java_objectheader *proto_java_lang_NegativeArraySizeException;
180 java_objectheader *proto_java_lang_OutOfMemoryError;
181 java_objectheader *proto_java_lang_ArithmeticException;
182 java_objectheader *proto_java_lang_ArrayStoreException;
183 java_objectheader *proto_java_lang_ThreadDeath;
185 /************* functions for reading classdata *********************************
187 getting classdata in blocks of variable size
188 (8,16,32,64-bit integer or float)
190 *******************************************************************************/
192 static char *classpath = ""; /* searchpath for classfiles */
193 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
194 static u1 *classbuf_pos; /* current position in classfile buffer */
195 static int classbuffer_size; /* size of classfile-data */
197 /* assert that at least <len> bytes are left to read */
198 /* <len> is limited to the range of non-negative s4 values */
199 #define ASSERT_LEFT(len) \
200 do {if ( ((s4)(len)) < 0 \
201 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
202 panic("Unexpected end of classfile"); } while(0)
204 /* transfer block of classfile data into a buffer */
206 #define suck_nbytes(buffer,len) \
207 do {ASSERT_LEFT(len); \
208 memcpy(buffer,classbuf_pos+1,len); \
209 classbuf_pos+=len;} while (0)
211 /* skip block of classfile data */
213 #define skip_nbytes(len) \
214 do {ASSERT_LEFT(len); \
215 classbuf_pos+=len;} while(0)
220 return *++classbuf_pos;
224 u1 a=suck_u1(), b=suck_u1();
225 return ((u2)a<<8)+(u2)b;
229 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
230 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
232 #define suck_s8() (s8) suck_u8()
233 #define suck_s2() (s2) suck_u2()
234 #define suck_s4() (s4) suck_u4()
235 #define suck_s1() (s1) suck_u1()
238 /* get u8 from classfile data */
245 return (hi << 32) + lo;
255 /* get float from classfile data */
256 static float suck_float()
263 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
264 memcpy((u1*) (&f), buffer, 4);
266 suck_nbytes((u1*) (&f), 4);
269 PANICIF (sizeof(float) != 4, "Incompatible float-format");
275 /* get double from classfile data */
276 static double suck_double()
283 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
284 memcpy((u1*) (&d), buffer, 8);
286 suck_nbytes((u1*) (&d), 8);
289 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
295 /************************** function suck_init *********************************
297 called once at startup, sets the searchpath for the classfiles
299 *******************************************************************************/
301 void suck_init(char *cpath)
308 union classpath_info *tmp;
309 union classpath_info *insertAfter=0;
314 if (classpath_entries) panic("suck_init should be called only once");
315 for(start=classpath;(*start)!='\0';) {
316 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
319 filenamelen=(end-start);
353 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
354 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
355 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
358 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
359 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
360 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
365 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
367 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
368 strncpy(filename,start,filenamelen);
369 filename[filenamelen+1]='\0';
374 unzFile uf=unzOpen(filename);
376 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
377 tmp->archive.type=CLASSPATH_ARCHIVE;
383 panic("Zip/JAR not supported");
387 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
388 tmp->filepath.type=CLASSPATH_PATH;
389 tmp->filepath.next=0;
390 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
391 filename[filenamelen]='/';
392 filename[filenamelen+1]='\0';
396 tmp->filepath.filename=filename;
397 tmp->filepath.pathlen=filenamelen;
403 insertAfter->filepath.next=tmp;
405 classpath_entries=tmp;
410 if ((*end)==':') start=end+1; else start=end;
413 if (filename!=0) free(filename);
418 /************************** function suck_start ********************************
420 returns true if classbuffer is already loaded or a file for the
421 specified class has succussfully been read in. All directories of
422 the searchpath are used to find the classfile (<classname>.class).
423 Returns false if no classfile is found and writes an error message.
425 *******************************************************************************/
427 bool suck_start(utf *classname)
429 classpath_info *currPos;
432 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
438 if (classbuffer) return true; /* classbuffer is already valid */
440 utf_ptr = classname->text;
441 while (utf_ptr < utf_end(classname)) {
442 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
444 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
446 filename[filenamelen++] = c;
448 strcpy(filename + filenamelen, ".class");
450 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
452 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
453 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
454 unz_file_info file_info;
455 /*log_text("Class found in zip file");*/
456 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
457 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
458 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
459 classbuffer_size = file_info.uncompressed_size;
460 classbuffer = MNEW(u1, classbuffer_size);
461 classbuf_pos = classbuffer - 1;
462 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
463 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
464 unzCloseCurrentFile(currPos->archive.uf);
467 MFREE(classbuffer, u1, classbuffer_size);
468 log_text("Error while unzipping");
470 } else log_text("Error while opening file in archive");
471 } else log_text("Error while retrieving fileinfo");
473 unzCloseCurrentFile(currPos->archive.uf);
477 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
478 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
479 classfile = fopen(currPos->filepath.filename, "r");
480 if (classfile) { /* file exists */
482 /* determine size of classfile */
484 /* dolog("File: %s",filename); */
486 err = stat(currPos->filepath.filename, &buffer);
488 if (!err) { /* read classfile data */
489 classbuffer_size = buffer.st_size;
490 classbuffer = MNEW(u1, classbuffer_size);
491 classbuf_pos = classbuffer - 1;
492 fread(classbuffer, 1, classbuffer_size, classfile);
503 dolog("Warning: Can not open class file '%s'", filename);
510 /************************** function suck_stop *********************************
512 frees memory for buffer with classfile data.
513 Caution: this function may only be called if buffer has been allocated
514 by suck_start with reading a file
516 *******************************************************************************/
520 /* determine amount of classdata not retrieved by suck-operations */
522 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
524 if (classdata_left > 0) {
526 dolog("There are %d extra bytes at end of classfile",
528 /* The JVM spec disallows extra bytes. */
529 panic("Extra bytes at end of classfile");
534 MFREE(classbuffer, u1, classbuffer_size);
539 /******************************************************************************/
540 /******************* Some support functions ***********************************/
541 /******************************************************************************/
543 void fprintflags (FILE *fp, u2 f)
545 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
546 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
547 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
548 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
549 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
550 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
551 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
552 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
553 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
554 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
555 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
559 /********** internal function: printflags (only for debugging) ***************/
561 void printflags(u2 f)
563 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
564 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
565 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
566 if ( f & ACC_STATIC ) printf (" STATIC");
567 if ( f & ACC_FINAL ) printf (" FINAL");
568 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
569 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
570 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
571 if ( f & ACC_NATIVE ) printf (" NATIVE");
572 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
573 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
577 /************************* Function: skipattribute *****************************
579 skips a (1) 'attribute' structure in the class file
581 *******************************************************************************/
583 static void skipattribute()
592 /********************** Function: skipattributebody ****************************
594 skips an attribute after the 16 bit reference to attribute_name has already
597 *******************************************************************************/
599 static void skipattributebody()
607 /************************* Function: skipattributes ****************************
609 skips num attribute structures
611 *******************************************************************************/
613 static void skipattributes(u4 num)
616 for (i = 0; i < num; i++)
621 /******************** function: innerclass_getconstant ************************
623 like class_getconstant, but if cptags is ZERO null is returned
625 *******************************************************************************/
627 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
629 /* invalid position in constantpool */
630 if (pos >= c->cpcount)
631 panic("Attempt to access constant outside range");
633 /* constantpool entry of type 0 */
637 /* check type of constantpool entry */
638 if (c->cptags[pos] != ctype) {
639 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
640 (int) ctype, (int) c->cptags[pos] );
643 return c->cpinfos[pos];
647 /************************ function: attribute_load ****************************
649 read attributes from classfile
651 *******************************************************************************/
653 static void attribute_load(u4 num, classinfo *c)
657 for (i = 0; i < num; i++) {
658 /* retrieve attribute name */
659 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
661 if (aname == utf_innerclasses) {
662 /* innerclasses attribute */
664 if (c->innerclass != NULL)
665 panic("Class has more than one InnerClasses attribute");
667 /* skip attribute length */
669 /* number of records */
670 c->innerclasscount = suck_u2();
671 /* allocate memory for innerclass structure */
672 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
674 for (j = 0; j < c->innerclasscount; j++) {
675 /* The innerclass structure contains a class with an encoded name,
676 its defining scope, its simple name and a bitmask of the access flags.
677 If an inner class is not a member, its outer_class is NULL,
678 if a class is anonymous, its name is NULL. */
680 innerclassinfo *info = c->innerclass + j;
682 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
683 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
684 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
685 info->flags = suck_u2(); /* access_flags bitmask */
689 /* unknown attribute */
696 /******************* function: checkfielddescriptor ****************************
698 checks whether a field-descriptor is valid and aborts otherwise
699 all referenced classes are inserted into the list of unloaded classes
701 *******************************************************************************/
703 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
705 class_from_descriptor(utf_ptr,end_pos,NULL,
707 | CLASSLOAD_NULLPRIMITIVE
709 | CLASSLOAD_CHECKEND);
711 /* XXX use the following if -noverify */
713 char *tstart; /* pointer to start of classname */
715 char *start = utf_ptr;
717 switch (*utf_ptr++) {
731 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
732 panic ("Ill formed descriptor");
736 panic ("Ill formed descriptor");
739 /* exceeding characters */
740 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
745 /******************* function checkmethoddescriptor ****************************
747 checks whether a method-descriptor is valid and aborts otherwise.
748 All referenced classes are inserted into the list of unloaded classes.
750 The number of arguments is returned. A long or double argument is counted
753 *******************************************************************************/
755 static int checkmethoddescriptor (utf *d)
757 char *utf_ptr = d->text; /* current position in utf text */
758 char *end_pos = utf_end(d); /* points behind utf string */
759 int argcount = 0; /* number of arguments */
761 /* method descriptor must start with parenthesis */
762 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
764 /* check arguments */
765 while (utf_ptr != end_pos && *utf_ptr != ')') {
766 /* We cannot count the this argument here because
767 * we don't know if the method is static. */
768 if (*utf_ptr == 'J' || *utf_ptr == 'D')
772 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
774 | CLASSLOAD_NULLPRIMITIVE
778 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
779 utf_ptr++; /* skip ')' */
781 class_from_descriptor(utf_ptr,end_pos,NULL,
783 | CLASSLOAD_NULLPRIMITIVE
784 | CLASSLOAD_CHECKEND);
787 panic("Invalid method descriptor: too many arguments");
791 /* XXX use the following if -noverify */
793 /* check arguments */
794 while ((c = *utf_ptr++) != ')') {
811 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
812 panic ("Ill formed method descriptor");
816 panic ("Ill formed methodtype-descriptor");
820 /* check returntype */
822 /* returntype void */
823 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
826 /* treat as field-descriptor */
827 checkfielddescriptor (utf_ptr,end_pos);
832 /***************** Function: print_arraydescriptor ****************************
834 Debugging helper for displaying an arraydescriptor
836 *******************************************************************************/
838 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
841 fprintf(file, "<NULL>");
846 if (desc->componentvftbl) {
847 if (desc->componentvftbl->class)
848 utf_fprint(file, desc->componentvftbl->class->name);
850 fprintf(file, "<no classinfo>");
856 if (desc->elementvftbl) {
857 if (desc->elementvftbl->class)
858 utf_fprint(file, desc->elementvftbl->class->name);
860 fprintf(file, "<no classinfo>");
864 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
865 desc->dataoffset, desc->componentsize);
869 /******************************************************************************/
870 /************************** Functions for fields ****************************/
871 /******************************************************************************/
874 /************************ Function: field_load *********************************
876 Load everything about a class field from the class file and fill a
877 'fieldinfo' structure. For static fields, space in the data segment is
880 *******************************************************************************/
882 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
884 static void field_load(fieldinfo *f, classinfo *c)
888 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
890 f->flags = suck_u2(); /* ACC flags */
891 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
892 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
896 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
897 panic("Field with invalid name");
899 /* check flag consistency */
900 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
901 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
902 panic("Field has invalid access flags");
903 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
904 panic("Field is declared final and volatile");
905 if ((c->flags & ACC_INTERFACE) != 0) {
906 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
907 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
908 panic("Interface field is not declared static final public");
909 if ((f->flags & ACC_TRANSIENT) != 0)
910 panic("Interface field declared transient");
913 /* check descriptor */
914 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
917 f->type = jtype = desc_to_type(f->descriptor); /* data type */
918 f->offset = 0; /* offset from start of object */
923 case TYPE_INT: f->value.i = 0; break;
924 case TYPE_FLOAT: f->value.f = 0.0; break;
925 case TYPE_DOUBLE: f->value.d = 0.0; break;
926 case TYPE_ADDRESS: f->value.a = NULL; break;
929 f->value.l = 0; break;
931 f->value.l.low = 0; f->value.l.high = 0; break;
935 /* read attributes */
937 for (i = 0; i < attrnum; i++) {
940 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
942 if (aname != utf_constantvalue) {
943 /* unknown attribute */
947 /* constant value attribute */
949 if (pindex != field_load_NOVALUE)
950 panic("Field has more than one ConstantValue attribute");
952 /* check attribute length */
954 panic("ConstantValue attribute has invalid length");
956 /* index of value in constantpool */
959 /* initialize field with value from constantpool */
962 constant_integer *ci =
963 class_getconstant(c, pindex, CONSTANT_Integer);
964 f->value.i = ci->value;
970 class_getconstant(c, pindex, CONSTANT_Long);
971 f->value.l = cl->value;
977 class_getconstant(c, pindex, CONSTANT_Float);
978 f->value.f = cf->value;
983 constant_double *cd =
984 class_getconstant(c, pindex, CONSTANT_Double);
985 f->value.d = cd->value;
990 utf *u = class_getconstant(c, pindex, CONSTANT_String);
991 /* create javastring from compressed utf8-string */
992 f->value.a = literalstring_new(u);
997 log_text ("Invalid Constant - Type");
1004 /********************** function: field_free **********************************/
1006 static void field_free (fieldinfo *f)
1012 /**************** Function: field_display (debugging only) ********************/
1014 void field_display(fieldinfo *f)
1017 printflags(f->flags);
1019 utf_display(f->name);
1021 utf_display(f->descriptor);
1022 printf(" offset: %ld\n", (long int) (f->offset));
1026 /******************************************************************************/
1027 /************************* Functions for methods ******************************/
1028 /******************************************************************************/
1031 /*********************** Function: method_load *********************************
1033 Loads a method from the class file and fills an existing 'methodinfo'
1034 structure. For native methods, the function pointer field is set to the
1035 real function pointer, for JavaVM methods a pointer to the compiler is used
1038 *******************************************************************************/
1040 static void method_load(methodinfo *m, classinfo *c)
1046 count_all_methods++;
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 skipattributebody();
1129 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1130 panic("Code attribute for native or abstract method");
1133 panic("Method has more than one Code attribute");
1136 m->maxstack = suck_u2();
1137 m->maxlocals = suck_u2();
1138 if (m->maxlocals < argcount)
1139 panic("max_locals is smaller than the number of arguments");
1141 codelen = suck_u4();
1143 panic("bytecode has zero length");
1144 if (codelen > 65536)
1145 panic("bytecode too long");
1146 m->jcodelength = codelen;
1147 m->jcode = MNEW(u1, m->jcodelength);
1148 suck_nbytes(m->jcode, m->jcodelength);
1149 m->exceptiontablelength = suck_u2();
1151 MNEW(exceptiontable, m->exceptiontablelength);
1154 count_vmcode_len += m->jcodelength + 18;
1155 count_extable_len += 8 * m->exceptiontablelength;
1158 for (e = 0; e < m->exceptiontablelength; e++) {
1160 m->exceptiontable[e].startpc = suck_u2();
1161 m->exceptiontable[e].endpc = suck_u2();
1162 m->exceptiontable[e].handlerpc = suck_u2();
1166 m->exceptiontable[e].catchtype = NULL;
1169 m->exceptiontable[e].catchtype =
1170 class_getconstant(c, idx, CONSTANT_Class);
1174 skipattributes(suck_u2());
1178 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1179 panic("Method missing Code attribute");
1183 /********************* Function: method_free ***********************************
1185 frees all memory that was allocated for this method
1187 *******************************************************************************/
1189 static void method_free(methodinfo *m)
1192 MFREE(m->jcode, u1, m->jcodelength);
1194 if (m->exceptiontable)
1195 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1198 CFREE(m->mcode, m->mcodelength);
1200 if (m->stubroutine) {
1201 if (m->flags & ACC_NATIVE) {
1202 removenativestub(m->stubroutine);
1205 removecompilerstub(m->stubroutine);
1211 /************** Function: method_display (debugging only) **************/
1213 void method_display(methodinfo *m)
1216 printflags(m->flags);
1218 utf_display(m->name);
1220 utf_display(m->descriptor);
1224 /************** Function: method_display_flags_last (debugging only) **************/
1226 void method_display_flags_last(methodinfo *m)
1229 utf_display(m->name);
1231 utf_display(m->descriptor);
1233 printflags(m->flags);
1238 /******************** Function: method_canoverwrite ****************************
1240 Check if m and old are identical with respect to type and name. This means
1241 that old can be overwritten with m.
1243 *******************************************************************************/
1245 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1247 if (m->name != old->name) return false;
1248 if (m->descriptor != old->descriptor) return false;
1249 if (m->flags & ACC_STATIC) return false;
1256 /******************************************************************************/
1257 /************************ Functions for class *********************************/
1258 /******************************************************************************/
1261 /******************** function:: class_getconstant ******************************
1263 retrieves the value at position 'pos' of the constantpool of a class
1264 if the type of the value is other than 'ctype' the system is stopped
1266 *******************************************************************************/
1268 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1270 /* invalid position in constantpool */
1271 /* (pos == 0 is caught by type comparison) */
1272 if (pos >= c->cpcount)
1273 panic("Attempt to access constant outside range");
1275 /* check type of constantpool entry */
1277 if (c->cptags[pos] != ctype) {
1278 class_showconstantpool(c);
1279 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1280 (int) ctype, (int) c->cptags[pos]);
1283 return c->cpinfos[pos];
1287 /********************* Function: class_constanttype ****************************
1289 Determines the type of a class entry in the ConstantPool
1291 *******************************************************************************/
1293 u4 class_constanttype(classinfo *c, u4 pos)
1295 if (pos >= c->cpcount)
1296 panic("Attempt to access constant outside range");
1298 return c->cptags[pos];
1302 /******************** function: class_loadcpool ********************************
1304 loads the constantpool of a class,
1305 the entries are transformed into a simpler format
1306 by resolving references
1307 (a detailed overview of the compact structures can be found in global.h)
1309 *******************************************************************************/
1311 static void class_loadcpool(classinfo *c)
1314 /* The following structures are used to save information which cannot be
1315 processed during the first pass. After the complete constantpool has
1316 been traversed the references can be resolved.
1317 (only in specific order) */
1319 /* CONSTANT_Class_info entries */
1320 typedef struct forward_class {
1321 struct forward_class *next;
1326 /* CONSTANT_String */
1327 typedef struct forward_string {
1328 struct forward_string *next;
1333 /* CONSTANT_NameAndType */
1334 typedef struct forward_nameandtype {
1335 struct forward_nameandtype *next;
1339 } forward_nameandtype;
1341 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1342 typedef struct forward_fieldmethint {
1343 struct forward_fieldmethint *next;
1347 u2 nameandtype_index;
1348 } forward_fieldmethint;
1352 long int dumpsize = dump_size ();
1354 forward_class *forward_classes = NULL;
1355 forward_string *forward_strings = NULL;
1356 forward_nameandtype *forward_nameandtypes = NULL;
1357 forward_fieldmethint *forward_fieldmethints = NULL;
1359 /* number of entries in the constant_pool table plus one */
1360 u4 cpcount = c -> cpcount = suck_u2();
1361 /* allocate memory */
1362 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1363 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1366 panic("Invalid constant_pool_count (0)");
1369 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1372 /* initialize constantpool */
1373 for (idx=0; idx<cpcount; idx++) {
1374 cptags[idx] = CONSTANT_UNUSED;
1375 cpinfos[idx] = NULL;
1379 /******* first pass *******/
1380 /* entries which cannot be resolved now are written into
1381 temporary structures and traversed again later */
1384 while (idx < cpcount) {
1385 /* get constant type */
1389 case CONSTANT_Class: {
1390 forward_class *nfc = DNEW(forward_class);
1392 nfc -> next = forward_classes;
1393 forward_classes = nfc;
1395 nfc -> thisindex = idx;
1396 /* reference to CONSTANT_NameAndType */
1397 nfc -> name_index = suck_u2 ();
1403 case CONSTANT_Fieldref:
1404 case CONSTANT_Methodref:
1405 case CONSTANT_InterfaceMethodref: {
1406 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1408 nff -> next = forward_fieldmethints;
1409 forward_fieldmethints = nff;
1411 nff -> thisindex = idx;
1414 /* class or interface type that contains the declaration of the field or method */
1415 nff -> class_index = suck_u2 ();
1416 /* name and descriptor of the field or method */
1417 nff -> nameandtype_index = suck_u2 ();
1423 case CONSTANT_String: {
1424 forward_string *nfs = DNEW (forward_string);
1426 nfs -> next = forward_strings;
1427 forward_strings = nfs;
1429 nfs -> thisindex = idx;
1430 /* reference to CONSTANT_Utf8_info with string characters */
1431 nfs -> string_index = suck_u2 ();
1437 case CONSTANT_NameAndType: {
1438 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1440 nfn -> next = forward_nameandtypes;
1441 forward_nameandtypes = nfn;
1443 nfn -> thisindex = idx;
1444 /* reference to CONSTANT_Utf8_info containing simple name */
1445 nfn -> name_index = suck_u2 ();
1446 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1447 nfn -> sig_index = suck_u2 ();
1453 case CONSTANT_Integer: {
1454 constant_integer *ci = NEW (constant_integer);
1457 count_const_pool_len += sizeof(constant_integer);
1460 ci -> value = suck_s4 ();
1461 cptags [idx] = CONSTANT_Integer;
1468 case CONSTANT_Float: {
1469 constant_float *cf = NEW (constant_float);
1472 count_const_pool_len += sizeof(constant_float);
1475 cf -> value = suck_float ();
1476 cptags [idx] = CONSTANT_Float;
1482 case CONSTANT_Long: {
1483 constant_long *cl = NEW(constant_long);
1486 count_const_pool_len += sizeof(constant_long);
1489 cl -> value = suck_s8 ();
1490 cptags [idx] = CONSTANT_Long;
1494 panic("Long constant exceeds constant pool");
1498 case CONSTANT_Double: {
1499 constant_double *cd = NEW(constant_double);
1502 count_const_pool_len += sizeof(constant_double);
1505 cd -> value = suck_double ();
1506 cptags [idx] = CONSTANT_Double;
1510 panic("Double constant exceeds constant pool");
1514 case CONSTANT_Utf8: {
1516 /* number of bytes in the bytes array (not string-length) */
1517 u4 length = suck_u2();
1518 cptags [idx] = CONSTANT_Utf8;
1519 /* validate the string */
1520 ASSERT_LEFT(length);
1522 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1524 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1525 panic("Invalid UTF-8 string");
1527 /* insert utf-string into the utf-symboltable */
1528 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1529 /* skip bytes of the string */
1530 skip_nbytes(length);
1536 error ("Unkown constant type: %d",(int) t);
1544 /* resolve entries in temporary structures */
1546 while (forward_classes) {
1548 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1550 if (opt_verify && !is_valid_name_utf(name))
1551 panic("Class reference with invalid name");
1553 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1554 /* retrieve class from class-table */
1555 cpinfos [forward_classes -> thisindex] = class_new (name);
1557 forward_classes = forward_classes -> next;
1561 while (forward_strings) {
1563 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1565 log_text("forward_string:");
1566 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1568 log_text("\n------------------"); */
1569 /* resolve utf-string */
1570 cptags [forward_strings -> thisindex] = CONSTANT_String;
1571 cpinfos [forward_strings -> thisindex] = text;
1573 forward_strings = forward_strings -> next;
1576 while (forward_nameandtypes) {
1577 constant_nameandtype *cn = NEW (constant_nameandtype);
1580 count_const_pool_len += sizeof(constant_nameandtype);
1583 /* resolve simple name and descriptor */
1584 cn -> name = class_getconstant
1585 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1586 cn -> descriptor = class_getconstant
1587 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1591 if (!is_valid_name_utf(cn->name))
1592 panic("NameAndType with invalid name");
1593 /* disallow referencing <clinit> among others */
1594 if (cn->name->text[0] == '<' && cn->name != utf_init)
1595 panic("NameAndType with invalid special name");
1598 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1599 cpinfos [forward_nameandtypes -> thisindex] = cn;
1601 forward_nameandtypes = forward_nameandtypes -> next;
1605 while (forward_fieldmethints) {
1606 constant_nameandtype *nat;
1607 constant_FMIref *fmi = NEW (constant_FMIref);
1610 count_const_pool_len += sizeof(constant_FMIref);
1612 /* resolve simple name and descriptor */
1613 nat = class_getconstant
1614 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1617 log_text("trying to resolve:");
1618 log_text(nat->name->text);
1619 switch(forward_fieldmethints ->tag) {
1620 case CONSTANT_Fieldref:
1621 log_text("CONSTANT_Fieldref");
1623 case CONSTANT_InterfaceMethodref:
1624 log_text("CONSTANT_InterfaceMethodref");
1626 case CONSTANT_Methodref:
1627 log_text("CONSTANT_Methodref");
1631 fmi -> class = class_getconstant
1632 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1633 fmi -> name = nat -> name;
1634 fmi -> descriptor = nat -> descriptor;
1636 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1637 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1639 switch (forward_fieldmethints -> tag) {
1640 case CONSTANT_Fieldref: /* check validity of descriptor */
1641 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1643 case CONSTANT_InterfaceMethodref:
1644 case CONSTANT_Methodref: /* check validity of descriptor */
1645 checkmethoddescriptor (fmi->descriptor);
1649 forward_fieldmethints = forward_fieldmethints -> next;
1653 /* class_showconstantpool(c); */
1655 dump_release (dumpsize);
1659 /********************** Function: class_load ***********************************
1661 Loads everything interesting about a class from the class file. The
1662 'classinfo' structure must have been allocated previously.
1664 The super class and the interfaces implemented by this class need not be
1665 loaded. The link is set later by the function 'class_link'.
1667 The loaded class is removed from the list 'unloadedclasses' and added to
1668 the list 'unlinkedclasses'.
1670 *******************************************************************************/
1672 static int class_load(classinfo *c)
1678 count_class_loads++;
1681 /* output for debugging purposes */
1683 char logtext[MAXLOGTEXT];
1684 sprintf(logtext, "Loading class: ");
1685 utf_sprint(logtext + strlen(logtext), c->name);
1689 /* load classdata, throw exception on error */
1691 if (!suck_start(c->name)) {
1692 throw_noclassdeffounderror_message(c->name);
1696 /* check signature */
1697 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1701 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1702 error("File version %d.%d is not supported", (int) ma, (int) mi);
1707 c->erroneous_state = 0;
1708 c->initializing_thread = 0;
1710 c->classUsed = NOTUSED; /* not used initially CO-RT */
1714 c->flags = suck_u2();
1715 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1717 /* check ACC flags consistency */
1718 if ((c->flags & ACC_INTERFACE) != 0) {
1719 if ((c->flags & ACC_ABSTRACT) == 0) {
1720 /* We work around this because interfaces in JDK 1.1 are
1721 * not declared abstract. */
1723 c->flags |= ACC_ABSTRACT;
1724 /* panic("Interface class not declared abstract"); */
1726 if ((c->flags & (ACC_FINAL)) != 0)
1727 panic("Interface class has invalid flags");
1728 if ((c->flags & (ACC_SUPER)) != 0)
1729 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1731 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1732 panic("Class is declared both abstract and final");
1736 if (class_getconstant(c, i, CONSTANT_Class) != c)
1737 panic("Invalid this_class in class file");
1739 /* retrieve superclass */
1740 if ((i = suck_u2())) {
1741 c->super = class_getconstant(c, i, CONSTANT_Class);
1743 /* java.lang.Object may not have a super class. */
1744 if (c->name == utf_java_lang_Object)
1745 panic("java.lang.Object with super class");
1747 /* Interfaces must have j.l.O as super class. */
1748 if ((c->flags & ACC_INTERFACE) != 0
1749 && c->super->name != utf_java_lang_Object)
1751 panic("Interface with super class other than java.lang.Object");
1756 /* This is only allowed for java.lang.Object. */
1757 if (c->name != utf_java_lang_Object)
1758 panic("Class (not java.lang.Object) without super class");
1761 /* retrieve interfaces */
1762 c->interfacescount = suck_u2();
1763 c->interfaces = MNEW(classinfo*, c->interfacescount);
1764 for (i = 0; i < c->interfacescount; i++) {
1766 class_getconstant(c, suck_u2(), CONSTANT_Class);
1770 c->fieldscount = suck_u2();
1771 /* utf_display(c->name);
1772 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1774 c->fields = GCNEW(fieldinfo, c->fieldscount);
1775 for (i = 0; i < c->fieldscount; i++) {
1776 field_load(&(c->fields[i]), c);
1780 c->methodscount = suck_u2();
1781 c->methods = MNEW(methodinfo, c->methodscount);
1782 for (i = 0; i < c->methodscount; i++) {
1783 method_load(&(c->methods[i]), c);
1786 /* Check if all fields and methods can be uniquely
1787 * identified by (name,descriptor). */
1789 /* We use a hash table here to avoid making the
1790 * average case quadratic in # of methods, fields.
1792 static int shift = 0;
1794 u2 *next; /* for chaining colliding hash entries */
1800 /* Allocate hashtable */
1801 len = c->methodscount;
1802 if (len < c->fieldscount) len = c->fieldscount;
1804 hashtab = MNEW(u2,(hashlen + len));
1805 next = hashtab + hashlen;
1807 /* Determine bitshift (to get good hash values) */
1817 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1818 for (i = 0; i<c->fieldscount; ++i) {
1819 fieldinfo *fi = c->fields + i;
1820 /* It's ok if we lose bits here */
1821 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1823 if ((old = hashtab[index]) != 0) {
1825 /* dolog("HASHHIT %d --> %d",index,old); */
1828 /* dolog("HASHCHECK %d",old); */
1829 if (c->fields[old].name == fi->name
1830 && c->fields[old].descriptor == fi->descriptor)
1832 dolog("Duplicate field (%d,%d):",i,old);
1833 log_utf(fi->name); log_utf(fi->descriptor);
1834 panic("Fields with same name and descriptor");
1836 } while ((old = next[old]) != 0);
1838 /* else dolog("HASHLUCKY"); */
1839 hashtab[index] = i+1;
1843 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1844 for (i = 0; i<c->methodscount; ++i) {
1845 methodinfo *mi = c->methods + i;
1846 /* It's ok if we lose bits here */
1847 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1849 if ((old = hashtab[index]) != 0) {
1851 /* dolog("HASHHIT %d --> %d",index,old); */
1854 /* dolog("HASHCHECK %d",old); */
1855 if (c->methods[old].name == mi->name
1856 && c->methods[old].descriptor == mi->descriptor)
1858 dolog("Duplicate method (%d,%d):",i,old);
1859 log_utf(mi->name); log_utf(mi->descriptor);
1860 panic("Methods with same name and descriptor");
1862 } while ((old = next[old]) != 0);
1864 /* else dolog("HASHLUCKY"); */
1865 hashtab[index] = i+1;
1868 MFREE(hashtab,u2,(hashlen + len));
1872 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1873 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1874 count_class_infos += sizeof(methodinfo) * c->methodscount;
1877 /* load variable-length attribute structures */
1878 attribute_load(suck_u2(), c);
1883 /* remove class from list of unloaded classes and
1884 add to list of unlinked classes */
1885 list_remove(&unloadedclasses, c);
1886 list_addlast(&unlinkedclasses, c);
1895 /************** internal Function: class_highestinterface ***********************
1897 Used by the function class_link to determine the amount of memory needed
1898 for the interface table.
1900 *******************************************************************************/
1902 static s4 class_highestinterface(classinfo *c)
1907 if (!(c->flags & ACC_INTERFACE)) {
1908 char logtext[MAXLOGTEXT];
1909 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1910 utf_sprint(logtext + strlen(logtext), c->name);
1911 error("%s",logtext);
1915 for (i = 0; i < c->interfacescount; i++) {
1916 s4 h2 = class_highestinterface(c->interfaces[i]);
1924 /* class_addinterface **********************************************************
1926 Is needed by class_link for adding a VTBL to a class. All interfaces
1927 implemented by ic are added as well.
1929 *******************************************************************************/
1931 static void class_addinterface (classinfo *c, classinfo *ic)
1935 vftbl *vftbl = c->vftbl;
1937 if (i >= vftbl->interfacetablelength)
1938 panic ("Inernal error: interfacetable overflow");
1939 if (vftbl->interfacetable[-i])
1942 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1943 vftbl->interfacevftbllength[i] = 1;
1944 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1945 vftbl->interfacetable[-i][0] = NULL;
1948 vftbl->interfacevftbllength[i] = ic->methodscount;
1949 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1952 count_vftbl_len += sizeof(methodptr) *
1953 (ic->methodscount + (ic->methodscount == 0));
1956 for (j=0; j<ic->methodscount; j++) {
1959 for (m = 0; m < sc->methodscount; m++) {
1960 methodinfo *mi = &(sc->methods[m]);
1961 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1962 vftbl->interfacetable[-i][j] =
1963 vftbl->table[mi->vftblindex];
1973 for (j = 0; j < ic->interfacescount; j++)
1974 class_addinterface(c, ic->interfaces[j]);
1978 /******************* Function: class_new_array *********************************
1980 This function is called by class_new to setup an array class.
1982 *******************************************************************************/
1984 void class_new_array(classinfo *c)
1986 classinfo *comp = NULL;
1990 /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
1992 /* Array classes are not loaded from classfiles. */
1993 list_remove(&unloadedclasses, c);
1995 /* Check array class name */
1996 namelen = c->name->blength;
1997 if (namelen < 2 || c->name->text[0] != '[')
1998 panic("Invalid array class name");
2000 /* Check the component type */
2001 switch (c->name->text[1]) {
2003 /* c is an array of arrays. We have to create the component class. */
2004 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
2008 /* c is an array of objects. */
2009 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2010 panic("Invalid array class name");
2011 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2015 /* Setup the array class */
2016 c->super = class_java_lang_Object;
2017 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2019 c->interfacescount = 2;
2020 c->interfaces = MNEW(classinfo*,2);
2021 c->interfaces[0] = class_java_lang_Cloneable;
2022 c->interfaces[1] = class_java_io_Serializable;
2024 c->methodscount = 1;
2025 c->methods = MNEW (methodinfo, c->methodscount);
2028 memset(clone, 0, sizeof(methodinfo));
2029 clone->flags = ACC_PUBLIC;
2030 clone->name = utf_new_char("clone");
2031 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2033 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2034 clone->monoPoly = MONO;
2036 /* XXX: field: length? */
2038 /* The array class has to be linked */
2039 list_addlast(&unlinkedclasses,c);
2042 * Array classes which are created after the other classes have been
2043 * loaded and linked are linked explicitely.
2048 loader_load(c->name); /* XXX handle errors */
2052 /****************** Function: class_link_array *********************************
2054 This function is called by class_link to create the
2055 arraydescriptor for an array class.
2057 This function returns NULL if the array cannot be linked because
2058 the component type has not been linked yet.
2060 *******************************************************************************/
2062 static arraydescriptor *class_link_array(classinfo *c)
2064 classinfo *comp = NULL;
2065 int namelen = c->name->blength;
2066 arraydescriptor *desc;
2069 /* Check the component type */
2070 switch (c->name->text[1]) {
2072 /* c is an array of arrays. */
2073 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2074 if (!comp) panic("Could not find component array class.");
2078 /* c is an array of objects. */
2079 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2080 if (!comp) panic("Could not find component class.");
2084 /* If the component type has not been linked return NULL */
2085 if (comp && !comp->linked)
2088 /* Allocate the arraydescriptor */
2089 desc = NEW(arraydescriptor);
2092 /* c is an array of references */
2093 desc->arraytype = ARRAYTYPE_OBJECT;
2094 desc->componentsize = sizeof(void*);
2095 desc->dataoffset = OFFSET(java_objectarray,data);
2097 compvftbl = comp->vftbl;
2099 panic("Component class has no vftbl");
2100 desc->componentvftbl = compvftbl;
2102 if (compvftbl->arraydesc) {
2103 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2104 if (compvftbl->arraydesc->dimension >= 255)
2105 panic("Creating array of dimension >255");
2106 desc->dimension = compvftbl->arraydesc->dimension + 1;
2107 desc->elementtype = compvftbl->arraydesc->elementtype;
2110 desc->elementvftbl = compvftbl;
2111 desc->dimension = 1;
2112 desc->elementtype = ARRAYTYPE_OBJECT;
2116 /* c is an array of a primitive type */
2117 switch (c->name->text[1]) {
2118 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2119 desc->dataoffset = OFFSET(java_booleanarray,data);
2120 desc->componentsize = sizeof(u1);
2123 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2124 desc->dataoffset = OFFSET(java_bytearray,data);
2125 desc->componentsize = sizeof(u1);
2128 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2129 desc->dataoffset = OFFSET(java_chararray,data);
2130 desc->componentsize = sizeof(u2);
2133 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2134 desc->dataoffset = OFFSET(java_doublearray,data);
2135 desc->componentsize = sizeof(double);
2138 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2139 desc->dataoffset = OFFSET(java_floatarray,data);
2140 desc->componentsize = sizeof(float);
2143 case 'I': desc->arraytype = ARRAYTYPE_INT;
2144 desc->dataoffset = OFFSET(java_intarray,data);
2145 desc->componentsize = sizeof(s4);
2148 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2149 desc->dataoffset = OFFSET(java_longarray,data);
2150 desc->componentsize = sizeof(s8);
2153 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2154 desc->dataoffset = OFFSET(java_shortarray,data);
2155 desc->componentsize = sizeof(s2);
2159 panic("Invalid array class name");
2162 desc->componentvftbl = NULL;
2163 desc->elementvftbl = NULL;
2164 desc->dimension = 1;
2165 desc->elementtype = desc->arraytype;
2172 /********************** Function: class_link ***********************************
2174 Tries to link a class. The super class and every implemented interface must
2175 already have been linked. The function calculates the length in bytes that
2176 an instance of this class requires as well as the VTBL for methods and
2179 If the class can be linked, it is removed from the list 'unlinkedclasses'
2180 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2183 Attention: If cyclical class definitions are encountered, the program gets
2184 into an infinite loop (we'll have to work that out)
2186 *******************************************************************************/
2188 void class_link(classinfo *c)
2190 s4 supervftbllength; /* vftbllegnth of super class */
2191 s4 vftbllength; /* vftbllength of current class */
2192 s4 interfacetablelength; /* interface table length */
2193 classinfo *super = c->super; /* super class */
2194 classinfo *ic, *c2; /* intermediate class variables */
2195 vftbl *v; /* vftbl of current class */
2196 s4 i; /* interface/method/field counter */
2197 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2200 /* check if all superclasses are already linked, if not put c at end of
2201 unlinked list and return. Additionally initialize class fields. */
2203 /* check interfaces */
2205 for (i = 0; i < c->interfacescount; i++) {
2206 ic = c->interfaces[i];
2208 list_remove(&unlinkedclasses, c);
2209 list_addlast(&unlinkedclasses, c);
2212 if ((ic->flags & ACC_INTERFACE) == 0) {
2213 dolog("Specified interface is not declared as interface:");
2217 panic("Specified interface is not declared as interface");
2221 /* check super class */
2223 if (super == NULL) { /* class java.long.Object */
2225 c->classUsed = USED; /* Object class is always used CO-RT*/
2227 c->instancesize = sizeof(java_objectheader);
2229 vftbllength = supervftbllength = 0;
2231 c->finalizer = NULL;
2234 if (!super->linked) {
2235 list_remove(&unlinkedclasses, c);
2236 list_addlast(&unlinkedclasses, c);
2240 if ((super->flags & ACC_INTERFACE) != 0)
2241 panic("Interface specified as super class");
2243 /* handle array classes */
2244 /* The component class must have been linked already. */
2245 if (c->name->text[0] == '[')
2246 if ((arraydesc = class_link_array(c)) == NULL) {
2247 list_remove(&unlinkedclasses, c);
2248 list_addlast(&unlinkedclasses, c);
2252 /* Don't allow extending final classes */
2253 if ((super->flags & ACC_FINAL) != 0)
2254 panic("Trying to extend final class");
2256 if (c->flags & ACC_INTERFACE)
2257 c->index = interfaceindex++;
2259 c->index = super->index + 1;
2261 c->instancesize = super->instancesize;
2263 vftbllength = supervftbllength = super->vftbl->vftbllength;
2265 c->finalizer = super->finalizer;
2270 char logtext[MAXLOGTEXT];
2271 sprintf(logtext, "Linking Class: ");
2272 utf_sprint(logtext + strlen(logtext), c->name );
2276 /* compute vftbl length */
2278 for (i = 0; i < c->methodscount; i++) {
2279 methodinfo *m = &(c->methods[i]);
2281 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2282 classinfo *sc = super;
2285 for (j = 0; j < sc->methodscount; j++) {
2286 if (method_canoverwrite(m, &(sc->methods[j]))) {
2287 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2288 goto notfoundvftblindex;
2289 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2292 log_utf(sc->methods[j].name);
2293 log_utf(sc->methods[j].descriptor);
2294 panic("Trying to overwrite final method");
2296 m->vftblindex = sc->methods[j].vftblindex;
2297 goto foundvftblindex;
2303 m->vftblindex = (vftbllength++);
2309 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2312 /* compute interfacetable length */
2314 interfacetablelength = 0;
2317 for (i = 0; i < c2->interfacescount; i++) {
2318 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2319 if (h > interfacetablelength)
2320 interfacetablelength = h;
2325 /* allocate virtual function table */
2327 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2328 (vftbllength - 1) + sizeof(methodptr*) *
2329 (interfacetablelength - (interfacetablelength > 0)));
2330 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2331 (interfacetablelength > 1));
2332 c->header.vftbl = c->vftbl = v;
2334 v->vftbllength = vftbllength;
2335 v->interfacetablelength = interfacetablelength;
2336 v->arraydesc = arraydesc;
2338 /* store interface index in vftbl */
2339 if (c->flags & ACC_INTERFACE)
2340 v->baseval = -(c->index);
2342 /* copy virtual function table of super class */
2344 for (i = 0; i < supervftbllength; i++)
2345 v->table[i] = super->vftbl->table[i];
2347 /* add method stubs into virtual function table */
2349 for (i = 0; i < c->methodscount; i++) {
2350 methodinfo *m = &(c->methods[i]);
2351 if (!(m->flags & ACC_STATIC)) {
2352 v->table[m->vftblindex] = m->stubroutine;
2356 /* compute instance size and offset of each field */
2358 for (i = 0; i < c->fieldscount; i++) {
2360 fieldinfo *f = &(c->fields[i]);
2362 if (!(f->flags & ACC_STATIC) ) {
2363 dsize = desc_typesize(f->descriptor);
2364 c->instancesize = ALIGN(c->instancesize, dsize);
2365 f->offset = c->instancesize;
2366 c->instancesize += dsize;
2370 /* initialize interfacetable and interfacevftbllength */
2372 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2375 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2378 for (i = 0; i < interfacetablelength; i++) {
2379 v->interfacevftbllength[i] = 0;
2380 v->interfacetable[-i] = NULL;
2383 /* add interfaces */
2385 for (c2 = c; c2 != NULL; c2 = c2->super)
2386 for (i = 0; i < c2->interfacescount; i++) {
2387 class_addinterface(c, c2->interfaces[i]);
2390 /* add finalizer method (not for java.lang.Object) */
2392 if (super != NULL) {
2394 static utf *finame = NULL;
2395 static utf *fidesc = NULL;
2398 finame = utf_finalize;
2400 fidesc = utf_fidesc;
2402 fi = class_findmethod(c, finame, fidesc);
2404 if (!(fi->flags & ACC_STATIC)) {
2414 list_remove(&unlinkedclasses, c);
2415 list_addlast(&linkedclasses, c);
2419 /******************* Function: class_freepool **********************************
2421 Frees all resources used by this classes Constant Pool.
2423 *******************************************************************************/
2425 static void class_freecpool (classinfo *c)
2431 for (idx=0; idx < c->cpcount; idx++) {
2432 tag = c->cptags[idx];
2433 info = c->cpinfos[idx];
2437 case CONSTANT_Fieldref:
2438 case CONSTANT_Methodref:
2439 case CONSTANT_InterfaceMethodref:
2440 FREE (info, constant_FMIref);
2442 case CONSTANT_Integer:
2443 FREE (info, constant_integer);
2445 case CONSTANT_Float:
2446 FREE (info, constant_float);
2449 FREE (info, constant_long);
2451 case CONSTANT_Double:
2452 FREE (info, constant_double);
2454 case CONSTANT_NameAndType:
2455 FREE (info, constant_nameandtype);
2461 MFREE (c -> cptags, u1, c -> cpcount);
2462 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2466 /*********************** Function: class_free **********************************
2468 Frees all resources used by the class.
2470 *******************************************************************************/
2472 static void class_free(classinfo *c)
2479 MFREE(c->interfaces, classinfo*, c->interfacescount);
2481 for (i = 0; i < c->fieldscount; i++)
2482 field_free(&(c->fields[i]));
2484 for (i = 0; i < c->methodscount; i++)
2485 method_free(&(c->methods[i]));
2486 MFREE(c->methods, methodinfo, c->methodscount);
2488 if ((v = c->vftbl) != NULL) {
2490 mem_free(v->arraydesc,sizeof(arraydescriptor));
2492 for (i = 0; i < v->interfacetablelength; i++) {
2493 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2495 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2497 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2498 sizeof(methodptr*) * (v->interfacetablelength -
2499 (v->interfacetablelength > 0));
2500 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2501 (v->interfacetablelength > 1));
2505 if (c->innerclasscount)
2506 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2508 /* if (c->classvftbl)
2509 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2515 /************************* Function: class_findfield ***************************
2517 Searches a 'classinfo' structure for a field having the given name and
2520 *******************************************************************************/
2522 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2526 for (i = 0; i < c->fieldscount; i++) {
2527 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2528 return &(c->fields[i]);
2531 panic("Can not find field given in CONSTANT_Fieldref");
2533 /* keep compiler happy */
2538 /************************* Function: class_findmethod **************************
2540 Searches a 'classinfo' structure for a method having the given name and
2541 type and returns the index in the class info structure.
2542 If type is NULL, it is ignored.
2544 *******************************************************************************/
2546 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2549 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2551 int buffer_len, pos;
2553 #ifdef JOWENN_DEBUG1
2556 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2558 buffer = MNEW(char, buffer_len);
2560 strcpy(buffer, "class_findmethod: method:");
2561 utf_sprint(buffer + strlen(buffer), name);
2562 strcpy(buffer + strlen(buffer), ", desc: ");
2563 utf_sprint(buffer + strlen(buffer), desc);
2564 strcpy(buffer + strlen(buffer), ", classname: ");
2565 utf_sprint(buffer + strlen(buffer), c->name);
2569 MFREE(buffer, char, buffer_len);
2571 for (i = 0; i < c->methodscount; i++) {
2572 #ifdef JOWENN_DEBUG2
2574 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2576 buffer = MNEW(char, buffer_len);
2578 strcpy(buffer, "class_findmethod: comparing to method:");
2579 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2580 strcpy(buffer + strlen(buffer), ", desc: ");
2581 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2585 MFREE(buffer, char, buffer_len);
2589 if ((c->methods[i].name == name) && ((desc == NULL) ||
2590 (c->methods[i].descriptor == desc))) {
2595 #ifdef JOWENN_DEBUG2
2596 class_showconstantpool(c);
2597 log_text("class_findmethod: returning NULL");
2604 /************************* Function: class_findmethod **************************
2606 Searches a 'classinfo' structure for a method having the given name and
2608 If type is NULL, it is ignored.
2610 *******************************************************************************/
2612 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2616 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2618 int buffer_len, pos;
2620 #ifdef JOWENN_DEBUG1
2623 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2625 buffer = MNEW(char, buffer_len);
2627 strcpy(buffer, "class_findmethod: method:");
2628 utf_sprint(buffer + strlen(buffer), name);
2629 strcpy(buffer + strlen(buffer), ", desc: ");
2630 utf_sprint(buffer + strlen(buffer), desc);
2631 strcpy(buffer + strlen(buffer), ", classname: ");
2632 utf_sprint(buffer + strlen(buffer), c->name);
2636 MFREE(buffer, char, buffer_len);
2638 for (i = 0; i < c->methodscount; i++) {
2639 #ifdef JOWENN_DEBUG2
2641 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2643 buffer = MNEW(char, buffer_len);
2645 strcpy(buffer, "class_findmethod: comparing to method:");
2646 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2647 strcpy(buffer + strlen(buffer), ", desc: ");
2648 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2652 MFREE(buffer, char, buffer_len);
2655 if ((c->methods[i].name == name) && ((desc == NULL) ||
2656 (c->methods[i].descriptor == desc))) {
2657 return &(c->methods[i]);
2660 #ifdef JOWENN_DEBUG2
2661 class_showconstantpool(c);
2662 log_text("class_findmethod: returning NULL");
2667 s4 idx=class_findmethodIndex(c, name, desc);
2668 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2669 if (idx == -1) return NULL;
2671 return &(c->methods[idx]);
2675 /*********************** Function: class_fetchmethod **************************
2677 like class_findmethod, but aborts with an error if the method is not found
2679 *******************************************************************************/
2681 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2684 mi = class_findmethod(c, name, desc);
2687 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2688 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2689 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2690 panic("Method not found");
2697 /*********************** Function: class_findmethod_w**************************
2699 like class_findmethod, but logs a warning if the method is not found
2701 *******************************************************************************/
2703 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2706 mi = class_findmethod(c, name, desc);
2709 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2710 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2711 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2713 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2714 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2715 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2716 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2717 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2718 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2719 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2720 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2721 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2722 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2723 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2726 log_plain(" : WARNING: Method not found");log_nl( );
2733 /************************* Function: class_findmethod_approx ******************
2735 like class_findmethod but ignores the return value when comparing the
2738 *******************************************************************************/
2740 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2744 for (i = 0; i < c->methodscount; i++) {
2745 if (c->methods[i].name == name) {
2746 utf *meth_descr = c->methods[i].descriptor;
2750 return &(c->methods[i]);
2752 if (desc->blength <= meth_descr->blength) {
2753 /* current position in utf text */
2754 char *desc_utf_ptr = desc->text;
2755 char *meth_utf_ptr = meth_descr->text;
2756 /* points behind utf strings */
2757 char *desc_end = utf_end(desc);
2758 char *meth_end = utf_end(meth_descr);
2761 /* compare argument types */
2762 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2764 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2765 break; /* no match */
2768 return &(c->methods[i]); /* all parameter types equal */
2778 /***************** Function: class_resolvemethod_approx ***********************
2780 Searches a class and every super class for a method (without paying
2781 attention to the return value)
2783 *******************************************************************************/
2785 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2788 /* search for method (ignore returntype) */
2789 methodinfo *m = class_findmethod_approx(c, name, desc);
2792 /* search superclass */
2800 /************************* Function: class_resolvemethod ***********************
2802 Searches a class and every super class for a method.
2804 *******************************************************************************/
2806 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2809 methodinfo *m = class_findmethod(c, name, desc);
2811 /* search superclass */
2819 /************************* Function: class_issubclass **************************
2821 Checks if sub is a descendant of super.
2823 *******************************************************************************/
2825 bool class_issubclass(classinfo *sub, classinfo *super)
2828 if (!sub) return false;
2829 if (sub == super) return true;
2835 /****************** Initialization function for classes ******************
2837 In Java, every class can have a static initialization function. This
2838 function has to be called BEFORE calling other methods or accessing static
2841 *******************************************************************************/
2843 void class_init(classinfo *c)
2847 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2851 if (!makeinitializations)
2856 c->initialized = true;
2859 count_class_inits++;
2862 /* initialize super class */
2865 char logtext[MAXLOGTEXT];
2866 sprintf(logtext, "Initialize super class ");
2867 utf_sprint(logtext + strlen(logtext), c->super->name);
2868 sprintf(logtext + strlen(logtext), " from ");
2869 utf_sprint(logtext + strlen(logtext), c->name);
2872 class_init(c->super);
2875 /* initialize interface classes */
2876 for (i = 0; i < c->interfacescount; i++) {
2878 char logtext[MAXLOGTEXT];
2879 sprintf(logtext, "Initialize interface class ");
2880 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2881 sprintf(logtext + strlen(logtext), " from ");
2882 utf_sprint(logtext + strlen(logtext), c->name);
2885 class_init(c->interfaces[i]); /* real */
2888 m = class_findmethod(c, utf_clinit, utf_fidesc);
2891 char logtext[MAXLOGTEXT];
2892 sprintf(logtext, "Class ");
2893 utf_sprint(logtext + strlen(logtext), c->name);
2894 sprintf(logtext + strlen(logtext), " has no initializer");
2897 /* goto callinitialize;*/
2901 if (!(m->flags & ACC_STATIC))
2902 panic("Class initializer is not static!");
2905 char logtext[MAXLOGTEXT];
2906 sprintf(logtext, "Starting initializer for class: ");
2907 utf_sprint(logtext + strlen(logtext), c->name);
2911 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2916 /* now call the initializer */
2917 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2919 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2920 assert(blockInts == 0);
2924 /* we have to throw an exception */
2925 if (*exceptionptr) {
2926 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2927 printf("Caused by: ");
2928 utf_display((*exceptionptr)->vftbl->class->name);
2935 char logtext[MAXLOGTEXT];
2936 sprintf(logtext, "Finished initializer for class: ");
2937 utf_sprint(logtext + strlen(logtext), c->name);
2941 if (c->name == utf_systemclass) {
2942 /* class java.lang.System requires explicit initialization */
2945 printf("#### Initializing class System");
2947 /* find initializing method */
2948 m = class_findmethod(c,
2949 utf_initsystemclass,
2953 /* no method found */
2954 /* printf("initializeSystemClass failed"); */
2958 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2963 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2965 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2966 assert(blockInts == 0);
2970 if (*exceptionptr) {
2971 printf("#### initializeSystemClass has thrown: ");
2972 utf_display((*exceptionptr)->vftbl->class->name);
2980 /********* Function: find_class_method_constant *********/
2982 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2987 for (i=0; i<c->cpcount; i++) {
2989 e = c -> cpinfos [i];
2992 switch (c -> cptags [i]) {
2993 case CONSTANT_Methodref:
2995 constant_FMIref *fmi = e;
2996 if ( (fmi->class->name == c1)
2997 && (fmi->name == m1)
2998 && (fmi->descriptor == d1)) {
3005 case CONSTANT_InterfaceMethodref:
3007 constant_FMIref *fmi = e;
3008 if ( (fmi->class->name == c1)
3009 && (fmi->name == m1)
3010 && (fmi->descriptor == d1)) {
3024 void class_showconstanti(classinfo *c, int ii)
3030 printf ("#%d: ", (int) i);
3032 switch (c->cptags [i]) {
3033 case CONSTANT_Class:
3034 printf("Classreference -> ");
3035 utf_display(((classinfo*)e)->name);
3038 case CONSTANT_Fieldref:
3039 printf("Fieldref -> "); goto displayFMIi;
3040 case CONSTANT_Methodref:
3041 printf("Methodref -> "); goto displayFMIi;
3042 case CONSTANT_InterfaceMethodref:
3043 printf("InterfaceMethod -> "); goto displayFMIi;
3046 constant_FMIref *fmi = e;
3047 utf_display(fmi->class->name);
3049 utf_display(fmi->name);
3051 utf_display(fmi->descriptor);
3055 case CONSTANT_String:
3056 printf("String -> ");
3059 case CONSTANT_Integer:
3060 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3062 case CONSTANT_Float:
3063 printf("Float -> %f", ((constant_float*)e)->value);
3065 case CONSTANT_Double:
3066 printf("Double -> %f", ((constant_double*)e)->value);
3070 u8 v = ((constant_long*)e)->value;
3072 printf("Long -> %ld", (long int) v);
3074 printf("Long -> HI: %ld, LO: %ld\n",
3075 (long int) v.high, (long int) v.low);
3079 case CONSTANT_NameAndType:
3081 constant_nameandtype *cnt = e;
3082 printf("NameAndType: ");
3083 utf_display(cnt->name);
3085 utf_display(cnt->descriptor);
3093 panic("Invalid type of ConstantPool-Entry");
3100 void class_showconstantpool (classinfo *c)
3105 printf ("---- dump of constant pool ----\n");
3107 for (i=0; i<c->cpcount; i++) {
3108 printf ("#%d: ", (int) i);
3110 e = c -> cpinfos [i];
3113 switch (c -> cptags [i]) {
3114 case CONSTANT_Class:
3115 printf ("Classreference -> ");
3116 utf_display ( ((classinfo*)e) -> name );
3119 case CONSTANT_Fieldref:
3120 printf ("Fieldref -> "); goto displayFMI;
3121 case CONSTANT_Methodref:
3122 printf ("Methodref -> "); goto displayFMI;
3123 case CONSTANT_InterfaceMethodref:
3124 printf ("InterfaceMethod -> "); goto displayFMI;
3127 constant_FMIref *fmi = e;
3128 utf_display ( fmi->class->name );
3130 utf_display ( fmi->name);
3132 utf_display ( fmi->descriptor );
3136 case CONSTANT_String:
3137 printf ("String -> ");
3140 case CONSTANT_Integer:
3141 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3143 case CONSTANT_Float:
3144 printf ("Float -> %f", ((constant_float*)e) -> value);
3146 case CONSTANT_Double:
3147 printf ("Double -> %f", ((constant_double*)e) -> value);
3151 u8 v = ((constant_long*)e) -> value;
3153 printf ("Long -> %ld", (long int) v);
3155 printf ("Long -> HI: %ld, LO: %ld\n",
3156 (long int) v.high, (long int) v.low);
3160 case CONSTANT_NameAndType:
3162 constant_nameandtype *cnt = e;
3163 printf ("NameAndType: ");
3164 utf_display (cnt->name);
3166 utf_display (cnt->descriptor);
3170 printf ("Utf8 -> ");
3174 panic ("Invalid type of ConstantPool-Entry");
3184 /********** Function: class_showmethods (debugging only) *************/
3186 void class_showmethods (classinfo *c)
3190 printf ("--------- Fields and Methods ----------------\n");
3191 printf ("Flags: "); printflags (c->flags); printf ("\n");
3193 printf ("This: "); utf_display (c->name); printf ("\n");
3195 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3197 printf ("Index: %d\n", c->index);
3199 printf ("interfaces:\n");
3200 for (i=0; i < c-> interfacescount; i++) {
3202 utf_display (c -> interfaces[i] -> name);
3203 printf (" (%d)\n", c->interfaces[i] -> index);
3206 printf ("fields:\n");
3207 for (i=0; i < c -> fieldscount; i++) {
3208 field_display (&(c -> fields[i]));
3211 printf ("methods:\n");
3212 for (i=0; i < c -> methodscount; i++) {
3213 methodinfo *m = &(c->methods[i]);
3214 if ( !(m->flags & ACC_STATIC))
3215 printf ("vftblindex: %d ", m->vftblindex);
3217 method_display ( m );
3221 printf ("Virtual function table:\n");
3222 for (i=0; i<c->vftbl->vftbllength; i++) {
3223 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3230 /******************************************************************************/
3231 /******************* General functions for the class loader *******************/
3232 /******************************************************************************/
3234 /********************* Function: loader_load ***********************************
3236 Loads and links the class desired class and each class and interface
3238 Returns: a pointer to this class
3240 *******************************************************************************/
3242 static int loader_load_running = 0;
3244 classinfo *loader_load(utf *topname)
3250 classinfo *notlinkable;
3252 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3253 pthread_mutex_lock(&compiler_mutex);
3256 /* avoid recursive calls */
3257 if (loader_load_running)
3258 return class_new(topname);
3260 loader_load_running++;
3262 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3267 starttime = getcputime();
3269 top = class_new(topname);
3272 while ((c = list_first(&unloadedclasses))) {
3273 if (!class_load(c)) {
3275 dolog("Failed to load class");
3276 list_remove(&unloadedclasses, c);
3283 dolog("Linking...");
3285 /* Added a hack to break infinite linking loops. A better
3286 * linking algorithm would be nice. -Edwin */
3288 while ((c = list_first(&unlinkedclasses))) {
3293 else if (notlinkable == c) {
3294 /* We tried to link this class for the second time and
3295 * no other classes were linked in between, so we are
3299 dolog("Cannot resolve linking dependencies");
3302 throw_linkageerror_message(c->name);
3310 dolog("Linking done.");
3313 loader_compute_subclasses();
3316 if (getloadingtime) {
3317 stoptime = getcputime();
3318 loadingtime += (stoptime - starttime);
3322 loader_load_running--;
3324 /* check if a former loader_load call tried to load/link the class and
3325 failed. This is needed because the class didn't appear in the
3326 undloadclasses or unlinkedclasses list during this class. */
3329 if (linkverbose) dolog("Failed to load class (former call)");
3330 throw_noclassdeffounderror_message(top->name);
3333 } else if (!top->linked) {
3335 dolog("Failed to link class (former call)");
3336 throw_linkageerror_message(top->name);
3341 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3345 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3346 pthread_mutex_unlock(&compiler_mutex);
3349 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3355 /****************** Function: loader_load_sysclass ****************************
3357 Loads and links the class desired class and each class and interface
3360 The pointer to the classinfo is stored in *top if top != NULL.
3361 The pointer is also returned.
3363 If the class could not be loaded the function aborts with an error.
3365 *******************************************************************************/
3367 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3371 if ((cls = loader_load(topname)) == NULL) {
3372 log_plain("Could not load important system class: ");
3373 log_plain_utf(topname);
3375 panic("Could not load important system class");
3378 if (top) *top = cls;
3384 /**************** function: create_primitive_classes ***************************
3386 create classes representing primitive types
3388 ********************************************************************************/
3391 void create_primitive_classes()
3395 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3396 /* create primitive class */
3397 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3398 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3399 c -> impldBy = NULL;
3401 /* prevent loader from loading primitive class */
3402 list_remove (&unloadedclasses, c);
3404 /* add to unlinked classes */
3405 list_addlast (&unlinkedclasses, c);
3406 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3409 primitivetype_table[i].class_primitive = c;
3411 /* create class for wrapping the primitive type */
3412 primitivetype_table[i].class_wrap =
3413 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3414 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3415 primitivetype_table[i].class_wrap -> impldBy = NULL;
3417 /* create the primitive array class */
3418 if (primitivetype_table[i].arrayname) {
3419 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3420 primitivetype_table[i].arrayclass = c;
3422 if (!c->linked) class_link(c);
3423 primitivetype_table[i].arrayvftbl = c->vftbl;
3428 /**************** function: class_primitive_from_sig ***************************
3430 return the primitive class indicated by the given signature character
3432 If the descriptor does not indicate a valid primitive type the
3433 return value is NULL.
3435 ********************************************************************************/
3437 classinfo *class_primitive_from_sig(char sig)
3440 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3441 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3442 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3443 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3444 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3445 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3446 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3447 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3448 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3453 /****************** function: class_from_descriptor ****************************
3455 return the class indicated by the given descriptor
3457 utf_ptr....first character of descriptor
3458 end_ptr....first character after the end of the string
3459 next.......if non-NULL, *next is set to the first character after
3460 the descriptor. (Undefined if an error occurs.)
3462 mode.......a combination (binary or) of the following flags:
3464 (Flags marked with * are the default settings.)
3466 What to do if a reference type descriptor is parsed successfully:
3468 CLASSLOAD_SKIP...skip it and return something != NULL
3469 * CLASSLOAD_NEW....get classinfo * via class_new
3470 CLASSLOAD_LOAD...get classinfo * via loader_load
3472 How to handle primitive types:
3474 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3475 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3477 How to handle "V" descriptors:
3479 * CLASSLOAD_VOID.....handle it like other primitive types
3480 CLASSLOAD_NOVOID...treat it as an error
3482 How to deal with extra characters after the end of the
3485 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3486 CLASSLOAD_CHECKEND.....treat them as an error
3488 How to deal with errors:
3490 * CLASSLOAD_PANIC....abort execution with an error message
3491 CLASSLOAD_NOPANIC..return NULL on error
3493 ********************************************************************************/
3495 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3496 char **next, int mode)
3498 char *start = utf_ptr;
3502 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3504 if (mode & CLASSLOAD_CHECKEND)
3505 error |= (utf_ptr != end_ptr);
3508 if (next) *next = utf_ptr;
3512 if (mode & CLASSLOAD_NOVOID)
3523 return (mode & CLASSLOAD_NULLPRIMITIVE)
3525 : class_primitive_from_sig(*start);
3532 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3533 name = utf_new(start,utf_ptr-start);
3534 return (mode & CLASSLOAD_LOAD)
3535 ? loader_load(name) : class_new(name); /* XXX handle errors */
3539 /* An error occurred */
3540 if (mode & CLASSLOAD_NOPANIC)
3543 log_plain("Invalid descriptor at beginning of '");
3544 log_plain_utf(utf_new(start, end_ptr-start));
3548 panic("Invalid descriptor");
3550 /* keep compiler happy */
3555 /******************* function: type_from_descriptor ****************************
3557 return the basic type indicated by the given descriptor
3559 This function parses a descriptor and returns its basic type as
3560 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3562 cls...if non-NULL the referenced variable is set to the classinfo *
3563 returned by class_from_descriptor.
3565 For documentation of the arguments utf_ptr, end_ptr, next and mode
3566 see class_from_descriptor. The only difference is that
3567 type_from_descriptor always uses CLASSLOAD_PANIC.
3569 ********************************************************************************/
3571 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3572 char **next, int mode)
3575 if (!cls) cls = &mycls;
3576 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3593 return TYPE_ADDRESS;
3598 /*************** function: create_system_exception_classes *******************************
3600 create system exception classes needed by default
3602 ********************************************************************************/
3604 static void create_system_exception_classes()
3607 if (verbose) log_text("loader_init: create_system_exception_classs: loader_load: java/lang/ClassCastException");
3608 loader_load_sysclass(&class_java_lang_ClassCastException,
3609 utf_new_char ("java/lang/ClassCastException"));
3610 loader_load_sysclass(&class_java_lang_NullPointerException,
3611 utf_new_char ("java/lang/NullPointerException"));
3612 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3613 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3614 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3615 utf_new_char ("java/lang/NegativeArraySizeException"));
3616 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3617 utf_new_char ("java/lang/OutOfMemoryError"));
3618 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3619 utf_new_char ("java/lang/ArrayStoreException"));
3620 loader_load_sysclass(&class_java_lang_ArithmeticException,
3621 utf_new_char ("java/lang/ArithmeticException"));
3622 loader_load_sysclass(&class_java_lang_ThreadDeath,
3623 utf_new_char ("java/lang/ThreadDeath"));
3629 /*************** function: create_system_exception_classes *******************************
3631 create system exception proto classes needed by default
3633 ********************************************************************************/
3635 static void create_system_exception_proto_classes()
3638 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3639 proto_java_lang_ClassCastException =
3640 builtin_new(class_java_lang_ClassCastException);
3642 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3644 proto_java_lang_NullPointerException =
3645 builtin_new(class_java_lang_NullPointerException);
3646 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3648 proto_java_lang_ArrayIndexOutOfBoundsException =
3649 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3651 proto_java_lang_NegativeArraySizeException =
3652 builtin_new(class_java_lang_NegativeArraySizeException);
3654 proto_java_lang_OutOfMemoryError =
3655 builtin_new(class_java_lang_OutOfMemoryError);
3657 proto_java_lang_ArithmeticException =
3658 builtin_new(class_java_lang_ArithmeticException);
3660 proto_java_lang_ArrayStoreException =
3661 builtin_new(class_java_lang_ArrayStoreException);
3663 proto_java_lang_ThreadDeath =
3664 builtin_new(class_java_lang_ThreadDeath);
3671 /*************** function: create_pseudo_classes *******************************
3673 create pseudo classes used by the typechecker
3675 ********************************************************************************/
3677 static void create_pseudo_classes()
3679 /* pseudo class for Arraystubs (extends java.lang.Object) */
3681 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3682 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3684 pseudo_class_Arraystub->super = class_java_lang_Object;
3685 pseudo_class_Arraystub->interfacescount = 2;
3686 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3687 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3688 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3690 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3691 class_link(pseudo_class_Arraystub);
3693 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3695 /* pseudo class representing the null type */
3697 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3698 list_remove(&unloadedclasses, pseudo_class_Null);
3700 pseudo_class_Null->super = class_java_lang_Object;
3702 list_addlast(&unlinkedclasses, pseudo_class_Null);
3703 class_link(pseudo_class_Null);
3705 /* pseudo class representing new uninitialized objects */
3707 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3708 list_remove(&unloadedclasses, pseudo_class_New);
3710 pseudo_class_New->super = class_java_lang_Object;
3712 list_addlast(&unlinkedclasses, pseudo_class_New);
3713 class_link(pseudo_class_New);
3717 /********************** Function: loader_init **********************************
3719 Initializes all lists and loads all classes required for the system or the
3722 *******************************************************************************/
3724 void loader_init(u1 *stackbottom)
3728 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3729 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3730 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3732 /* create utf-symbols for pointer comparison of frequently used strings */
3733 utf_innerclasses = utf_new_char("InnerClasses");
3734 utf_constantvalue = utf_new_char("ConstantValue");
3735 utf_code = utf_new_char("Code");
3736 utf_finalize = utf_new_char("finalize");
3737 utf_fidesc = utf_new_char("()V");
3738 utf_init = utf_new_char("<init>");
3739 utf_clinit = utf_new_char("<clinit>");
3740 utf_initsystemclass = utf_new_char("initializeSystemClass");
3741 utf_systemclass = utf_new_char("java/lang/System");
3742 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3743 utf_initialize = utf_new_char("initialize");
3744 utf_initializedesc = utf_new_char("(I)V");
3746 utf_vmclass = utf_new_char("java/lang/VMClass");
3747 utf_java_lang_Object= utf_new_char("java/lang/Object");
3749 array_packagename = utf_new_char("<the array package>");
3751 /* create some important classes */
3752 /* These classes have to be created now because the classinfo
3753 * pointers are used in the loading code.
3755 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3756 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3757 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3758 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3760 if (verbose) log_text("loader_init: java/lang/Object");
3761 /* load the classes which were created above */
3762 loader_load_sysclass(NULL, class_java_lang_Object->name);
3764 loader_inited = 1; /*JOWENN*/
3766 loader_load_sysclass(&class_java_lang_Throwable,
3767 utf_new_char("java/lang/Throwable"));
3769 create_system_exception_classes();
3771 /* create classes representing primitive types */
3772 create_primitive_classes();
3774 /* create classes used by the typechecker */
3775 create_pseudo_classes();
3777 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3778 stringtable_update();
3780 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3784 create_system_exception_proto_classes();
3790 /********************* Function: loader_initclasses ****************************
3792 Initializes all loaded but uninitialized classes
3794 *******************************************************************************/
3797 /* XXX TWISTI: i think we do not need this */
3798 void loader_initclasses ()
3802 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3803 pthread_mutex_lock(&compiler_mutex);
3806 intsDisable(); /* schani */
3808 if (makeinitializations) {
3809 c = list_first(&linkedclasses);
3812 c = list_next(&linkedclasses, c);
3816 intsRestore(); /* schani */
3818 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3819 pthread_mutex_unlock(&compiler_mutex);
3825 static void loader_compute_class_values(classinfo *c)
3829 c->vftbl->baseval = ++classvalue;
3832 while (subs != NULL) {
3833 loader_compute_class_values(subs);
3834 subs = subs->nextsub;
3836 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3841 for (i = 0; i < c->index; i++)
3843 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3844 utf_display(c->name);
3851 void loader_compute_subclasses()
3855 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3856 intsDisable(); /* schani */
3859 c = list_first(&linkedclasses);
3861 if (!(c->flags & ACC_INTERFACE)) {
3865 c = list_next(&linkedclasses, c);
3868 c = list_first(&linkedclasses);
3870 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3871 c->nextsub = c->super->sub;
3874 c = list_next(&linkedclasses, c);
3878 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3881 loader_compute_class_values(class_java_lang_Object);
3882 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3886 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3887 intsRestore(); /* schani */
3892 /******************** function classloader_buffer ******************************
3894 sets buffer for reading classdata
3896 *******************************************************************************/
3898 void classload_buffer(u1 *buf, int len)
3901 classbuffer_size = len;
3902 classbuf_pos = buf - 1;
3906 /******************** Function: loader_close ***********************************
3910 *******************************************************************************/
3916 while ((c = list_first(&unloadedclasses))) {
3917 list_remove(&unloadedclasses, c);
3920 while ((c = list_first(&unlinkedclasses))) {
3921 list_remove(&unlinkedclasses, c);
3924 while ((c = list_first(&linkedclasses))) {
3925 list_remove(&linkedclasses, c);
3932 * These are local overrides for various environment variables in Emacs.
3933 * Please do not remove this and leave it at the end of the file, where
3934 * Emacs will automagically detect them.
3935 * ---------------------------------------------------------------------
3938 * indent-tabs-mode: t