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 915 2004-02-05 23:13:19Z 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_FINAL) != 0) {
2290 log_utf(sc->methods[j].name);
2291 log_utf(sc->methods[j].descriptor);
2292 panic("Trying to overwrite final method");
2294 m->vftblindex = sc->methods[j].vftblindex;
2295 goto foundvftblindex;
2300 m->vftblindex = (vftbllength++);
2306 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2309 /* compute interfacetable length */
2311 interfacetablelength = 0;
2314 for (i = 0; i < c2->interfacescount; i++) {
2315 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2316 if (h > interfacetablelength)
2317 interfacetablelength = h;
2322 /* allocate virtual function table */
2324 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2325 (vftbllength - 1) + sizeof(methodptr*) *
2326 (interfacetablelength - (interfacetablelength > 0)));
2327 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2328 (interfacetablelength > 1));
2329 c->header.vftbl = c->vftbl = v;
2331 v->vftbllength = vftbllength;
2332 v->interfacetablelength = interfacetablelength;
2333 v->arraydesc = arraydesc;
2335 /* store interface index in vftbl */
2336 if (c->flags & ACC_INTERFACE)
2337 v->baseval = -(c->index);
2339 /* copy virtual function table of super class */
2341 for (i = 0; i < supervftbllength; i++)
2342 v->table[i] = super->vftbl->table[i];
2344 /* add method stubs into virtual function table */
2346 for (i = 0; i < c->methodscount; i++) {
2347 methodinfo *m = &(c->methods[i]);
2348 if (!(m->flags & ACC_STATIC)) {
2349 v->table[m->vftblindex] = m->stubroutine;
2353 /* compute instance size and offset of each field */
2355 for (i = 0; i < c->fieldscount; i++) {
2357 fieldinfo *f = &(c->fields[i]);
2359 if (!(f->flags & ACC_STATIC) ) {
2360 dsize = desc_typesize(f->descriptor);
2361 c->instancesize = ALIGN(c->instancesize, dsize);
2362 f->offset = c->instancesize;
2363 c->instancesize += dsize;
2367 /* initialize interfacetable and interfacevftbllength */
2369 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2372 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2375 for (i = 0; i < interfacetablelength; i++) {
2376 v->interfacevftbllength[i] = 0;
2377 v->interfacetable[-i] = NULL;
2380 /* add interfaces */
2382 for (c2 = c; c2 != NULL; c2 = c2->super)
2383 for (i = 0; i < c2->interfacescount; i++) {
2384 class_addinterface(c, c2->interfaces[i]);
2387 /* add finalizer method (not for java.lang.Object) */
2389 if (super != NULL) {
2391 static utf *finame = NULL;
2392 static utf *fidesc = NULL;
2395 finame = utf_finalize;
2397 fidesc = utf_fidesc;
2399 fi = class_findmethod(c, finame, fidesc);
2401 if (!(fi->flags & ACC_STATIC)) {
2411 list_remove(&unlinkedclasses, c);
2412 list_addlast(&linkedclasses, c);
2416 /******************* Function: class_freepool **********************************
2418 Frees all resources used by this classes Constant Pool.
2420 *******************************************************************************/
2422 static void class_freecpool (classinfo *c)
2428 for (idx=0; idx < c->cpcount; idx++) {
2429 tag = c->cptags[idx];
2430 info = c->cpinfos[idx];
2434 case CONSTANT_Fieldref:
2435 case CONSTANT_Methodref:
2436 case CONSTANT_InterfaceMethodref:
2437 FREE (info, constant_FMIref);
2439 case CONSTANT_Integer:
2440 FREE (info, constant_integer);
2442 case CONSTANT_Float:
2443 FREE (info, constant_float);
2446 FREE (info, constant_long);
2448 case CONSTANT_Double:
2449 FREE (info, constant_double);
2451 case CONSTANT_NameAndType:
2452 FREE (info, constant_nameandtype);
2458 MFREE (c -> cptags, u1, c -> cpcount);
2459 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2463 /*********************** Function: class_free **********************************
2465 Frees all resources used by the class.
2467 *******************************************************************************/
2469 static void class_free(classinfo *c)
2476 MFREE(c->interfaces, classinfo*, c->interfacescount);
2478 for (i = 0; i < c->fieldscount; i++)
2479 field_free(&(c->fields[i]));
2481 for (i = 0; i < c->methodscount; i++)
2482 method_free(&(c->methods[i]));
2483 MFREE(c->methods, methodinfo, c->methodscount);
2485 if ((v = c->vftbl) != NULL) {
2487 mem_free(v->arraydesc,sizeof(arraydescriptor));
2489 for (i = 0; i < v->interfacetablelength; i++) {
2490 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2492 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2494 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2495 sizeof(methodptr*) * (v->interfacetablelength -
2496 (v->interfacetablelength > 0));
2497 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2498 (v->interfacetablelength > 1));
2502 if (c->innerclasscount)
2503 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2505 /* if (c->classvftbl)
2506 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2512 /************************* Function: class_findfield ***************************
2514 Searches a 'classinfo' structure for a field having the given name and
2517 *******************************************************************************/
2519 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2523 for (i = 0; i < c->fieldscount; i++) {
2524 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2525 return &(c->fields[i]);
2528 panic("Can not find field given in CONSTANT_Fieldref");
2530 /* keep compiler happy */
2535 /************************* Function: class_findmethod **************************
2537 Searches a 'classinfo' structure for a method having the given name and
2538 type and returns the index in the class info structure.
2539 If type is NULL, it is ignored.
2541 *******************************************************************************/
2543 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2546 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2548 int buffer_len, pos;
2550 #ifdef JOWENN_DEBUG1
2553 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2555 buffer = MNEW(char, buffer_len);
2557 strcpy(buffer, "class_findmethod: method:");
2558 utf_sprint(buffer + strlen(buffer), name);
2559 strcpy(buffer + strlen(buffer), ", desc: ");
2560 utf_sprint(buffer + strlen(buffer), desc);
2561 strcpy(buffer + strlen(buffer), ", classname: ");
2562 utf_sprint(buffer + strlen(buffer), c->name);
2566 MFREE(buffer, char, buffer_len);
2568 for (i = 0; i < c->methodscount; i++) {
2569 #ifdef JOWENN_DEBUG2
2571 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2573 buffer = MNEW(char, buffer_len);
2575 strcpy(buffer, "class_findmethod: comparing to method:");
2576 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2577 strcpy(buffer + strlen(buffer), ", desc: ");
2578 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2582 MFREE(buffer, char, buffer_len);
2586 if ((c->methods[i].name == name) && ((desc == NULL) ||
2587 (c->methods[i].descriptor == desc))) {
2592 #ifdef JOWENN_DEBUG2
2593 class_showconstantpool(c);
2594 log_text("class_findmethod: returning NULL");
2601 /************************* Function: class_findmethod **************************
2603 Searches a 'classinfo' structure for a method having the given name and
2605 If type is NULL, it is ignored.
2607 *******************************************************************************/
2609 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2613 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2615 int buffer_len, pos;
2617 #ifdef JOWENN_DEBUG1
2620 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2622 buffer = MNEW(char, buffer_len);
2624 strcpy(buffer, "class_findmethod: method:");
2625 utf_sprint(buffer + strlen(buffer), name);
2626 strcpy(buffer + strlen(buffer), ", desc: ");
2627 utf_sprint(buffer + strlen(buffer), desc);
2628 strcpy(buffer + strlen(buffer), ", classname: ");
2629 utf_sprint(buffer + strlen(buffer), c->name);
2633 MFREE(buffer, char, buffer_len);
2635 for (i = 0; i < c->methodscount; i++) {
2636 #ifdef JOWENN_DEBUG2
2638 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2640 buffer = MNEW(char, buffer_len);
2642 strcpy(buffer, "class_findmethod: comparing to method:");
2643 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2644 strcpy(buffer + strlen(buffer), ", desc: ");
2645 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2649 MFREE(buffer, char, buffer_len);
2652 if ((c->methods[i].name == name) && ((desc == NULL) ||
2653 (c->methods[i].descriptor == desc))) {
2654 return &(c->methods[i]);
2657 #ifdef JOWENN_DEBUG2
2658 class_showconstantpool(c);
2659 log_text("class_findmethod: returning NULL");
2664 s4 idx=class_findmethodIndex(c, name, desc);
2665 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2666 if (idx == -1) return NULL;
2668 return &(c->methods[idx]);
2672 /*********************** Function: class_fetchmethod **************************
2674 like class_findmethod, but aborts with an error if the method is not found
2676 *******************************************************************************/
2678 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2681 mi = class_findmethod(c, name, desc);
2684 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2685 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2686 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2687 panic("Method not found");
2694 /*********************** Function: class_findmethod_w**************************
2696 like class_findmethod, but logs a warning if the method is not found
2698 *******************************************************************************/
2700 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2703 mi = class_findmethod(c, name, desc);
2706 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2707 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2708 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2710 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2711 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2712 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2713 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2714 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2715 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2716 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2717 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2718 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2719 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2720 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2723 log_plain(" : WARNING: Method not found");log_nl( );
2730 /************************* Function: class_findmethod_approx ******************
2732 like class_findmethod but ignores the return value when comparing the
2735 *******************************************************************************/
2737 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2741 for (i = 0; i < c->methodscount; i++) {
2742 if (c->methods[i].name == name) {
2743 utf *meth_descr = c->methods[i].descriptor;
2747 return &(c->methods[i]);
2749 if (desc->blength <= meth_descr->blength) {
2750 /* current position in utf text */
2751 char *desc_utf_ptr = desc->text;
2752 char *meth_utf_ptr = meth_descr->text;
2753 /* points behind utf strings */
2754 char *desc_end = utf_end(desc);
2755 char *meth_end = utf_end(meth_descr);
2758 /* compare argument types */
2759 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2761 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2762 break; /* no match */
2765 return &(c->methods[i]); /* all parameter types equal */
2775 /***************** Function: class_resolvemethod_approx ***********************
2777 Searches a class and every super class for a method (without paying
2778 attention to the return value)
2780 *******************************************************************************/
2782 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2785 /* search for method (ignore returntype) */
2786 methodinfo *m = class_findmethod_approx(c, name, desc);
2789 /* search superclass */
2797 /************************* Function: class_resolvemethod ***********************
2799 Searches a class and every super class for a method.
2801 *******************************************************************************/
2803 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2806 methodinfo *m = class_findmethod(c, name, desc);
2808 /* search superclass */
2816 /************************* Function: class_issubclass **************************
2818 Checks if sub is a descendant of super.
2820 *******************************************************************************/
2822 bool class_issubclass(classinfo *sub, classinfo *super)
2825 if (!sub) return false;
2826 if (sub == super) return true;
2832 /****************** Initialization function for classes ******************
2834 In Java, every class can have a static initialization function. This
2835 function has to be called BEFORE calling other methods or accessing static
2838 *******************************************************************************/
2840 void class_init(classinfo *c)
2844 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2848 if (!makeinitializations)
2853 c->initialized = true;
2856 count_class_inits++;
2859 /* initialize super class */
2862 char logtext[MAXLOGTEXT];
2863 sprintf(logtext, "Initialize super class ");
2864 utf_sprint(logtext + strlen(logtext), c->super->name);
2865 sprintf(logtext + strlen(logtext), " from ");
2866 utf_sprint(logtext + strlen(logtext), c->name);
2869 class_init(c->super);
2872 /* initialize interface classes */
2873 for (i = 0; i < c->interfacescount; i++) {
2875 char logtext[MAXLOGTEXT];
2876 sprintf(logtext, "Initialize interface class ");
2877 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2878 sprintf(logtext + strlen(logtext), " from ");
2879 utf_sprint(logtext + strlen(logtext), c->name);
2882 class_init(c->interfaces[i]); /* real */
2885 m = class_findmethod(c, utf_clinit, utf_fidesc);
2888 char logtext[MAXLOGTEXT];
2889 sprintf(logtext, "Class ");
2890 utf_sprint(logtext + strlen(logtext), c->name);
2891 sprintf(logtext + strlen(logtext), " has no initializer");
2894 /* goto callinitialize;*/
2898 if (!(m->flags & ACC_STATIC))
2899 panic("Class initializer is not static!");
2902 char logtext[MAXLOGTEXT];
2903 sprintf(logtext, "Starting initializer for class: ");
2904 utf_sprint(logtext + strlen(logtext), c->name);
2908 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2913 /* now call the initializer */
2914 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2916 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2917 assert(blockInts == 0);
2921 /* we have to throw an exception */
2922 if (*exceptionptr) {
2923 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2924 printf("Caused by: ");
2925 utf_display((*exceptionptr)->vftbl->class->name);
2932 char logtext[MAXLOGTEXT];
2933 sprintf(logtext, "Finished initializer for class: ");
2934 utf_sprint(logtext + strlen(logtext), c->name);
2938 if (c->name == utf_systemclass) {
2939 /* class java.lang.System requires explicit initialization */
2942 printf("#### Initializing class System");
2944 /* find initializing method */
2945 m = class_findmethod(c,
2946 utf_initsystemclass,
2950 /* no method found */
2951 /* printf("initializeSystemClass failed"); */
2955 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2960 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2962 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2963 assert(blockInts == 0);
2967 if (*exceptionptr) {
2968 printf("#### initializeSystemClass has thrown: ");
2969 utf_display((*exceptionptr)->vftbl->class->name);
2977 /********* Function: find_class_method_constant *********/
2979 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2984 for (i=0; i<c->cpcount; i++) {
2986 e = c -> cpinfos [i];
2989 switch (c -> cptags [i]) {
2990 case CONSTANT_Methodref:
2992 constant_FMIref *fmi = e;
2993 if ( (fmi->class->name == c1)
2994 && (fmi->name == m1)
2995 && (fmi->descriptor == d1)) {
3002 case CONSTANT_InterfaceMethodref:
3004 constant_FMIref *fmi = e;
3005 if ( (fmi->class->name == c1)
3006 && (fmi->name == m1)
3007 && (fmi->descriptor == d1)) {
3021 void class_showconstanti(classinfo *c, int ii)
3027 printf ("#%d: ", (int) i);
3029 switch (c->cptags [i]) {
3030 case CONSTANT_Class:
3031 printf("Classreference -> ");
3032 utf_display(((classinfo*)e)->name);
3035 case CONSTANT_Fieldref:
3036 printf("Fieldref -> "); goto displayFMIi;
3037 case CONSTANT_Methodref:
3038 printf("Methodref -> "); goto displayFMIi;
3039 case CONSTANT_InterfaceMethodref:
3040 printf("InterfaceMethod -> "); goto displayFMIi;
3043 constant_FMIref *fmi = e;
3044 utf_display(fmi->class->name);
3046 utf_display(fmi->name);
3048 utf_display(fmi->descriptor);
3052 case CONSTANT_String:
3053 printf("String -> ");
3056 case CONSTANT_Integer:
3057 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3059 case CONSTANT_Float:
3060 printf("Float -> %f", ((constant_float*)e)->value);
3062 case CONSTANT_Double:
3063 printf("Double -> %f", ((constant_double*)e)->value);
3067 u8 v = ((constant_long*)e)->value;
3069 printf("Long -> %ld", (long int) v);
3071 printf("Long -> HI: %ld, LO: %ld\n",
3072 (long int) v.high, (long int) v.low);
3076 case CONSTANT_NameAndType:
3078 constant_nameandtype *cnt = e;
3079 printf("NameAndType: ");
3080 utf_display(cnt->name);
3082 utf_display(cnt->descriptor);
3090 panic("Invalid type of ConstantPool-Entry");
3097 void class_showconstantpool (classinfo *c)
3102 printf ("---- dump of constant pool ----\n");
3104 for (i=0; i<c->cpcount; i++) {
3105 printf ("#%d: ", (int) i);
3107 e = c -> cpinfos [i];
3110 switch (c -> cptags [i]) {
3111 case CONSTANT_Class:
3112 printf ("Classreference -> ");
3113 utf_display ( ((classinfo*)e) -> name );
3116 case CONSTANT_Fieldref:
3117 printf ("Fieldref -> "); goto displayFMI;
3118 case CONSTANT_Methodref:
3119 printf ("Methodref -> "); goto displayFMI;
3120 case CONSTANT_InterfaceMethodref:
3121 printf ("InterfaceMethod -> "); goto displayFMI;
3124 constant_FMIref *fmi = e;
3125 utf_display ( fmi->class->name );
3127 utf_display ( fmi->name);
3129 utf_display ( fmi->descriptor );
3133 case CONSTANT_String:
3134 printf ("String -> ");
3137 case CONSTANT_Integer:
3138 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3140 case CONSTANT_Float:
3141 printf ("Float -> %f", ((constant_float*)e) -> value);
3143 case CONSTANT_Double:
3144 printf ("Double -> %f", ((constant_double*)e) -> value);
3148 u8 v = ((constant_long*)e) -> value;
3150 printf ("Long -> %ld", (long int) v);
3152 printf ("Long -> HI: %ld, LO: %ld\n",
3153 (long int) v.high, (long int) v.low);
3157 case CONSTANT_NameAndType:
3159 constant_nameandtype *cnt = e;
3160 printf ("NameAndType: ");
3161 utf_display (cnt->name);
3163 utf_display (cnt->descriptor);
3167 printf ("Utf8 -> ");
3171 panic ("Invalid type of ConstantPool-Entry");
3181 /********** Function: class_showmethods (debugging only) *************/
3183 void class_showmethods (classinfo *c)
3187 printf ("--------- Fields and Methods ----------------\n");
3188 printf ("Flags: "); printflags (c->flags); printf ("\n");
3190 printf ("This: "); utf_display (c->name); printf ("\n");
3192 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3194 printf ("Index: %d\n", c->index);
3196 printf ("interfaces:\n");
3197 for (i=0; i < c-> interfacescount; i++) {
3199 utf_display (c -> interfaces[i] -> name);
3200 printf (" (%d)\n", c->interfaces[i] -> index);
3203 printf ("fields:\n");
3204 for (i=0; i < c -> fieldscount; i++) {
3205 field_display (&(c -> fields[i]));
3208 printf ("methods:\n");
3209 for (i=0; i < c -> methodscount; i++) {
3210 methodinfo *m = &(c->methods[i]);
3211 if ( !(m->flags & ACC_STATIC))
3212 printf ("vftblindex: %d ", m->vftblindex);
3214 method_display ( m );
3218 printf ("Virtual function table:\n");
3219 for (i=0; i<c->vftbl->vftbllength; i++) {
3220 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3227 /******************************************************************************/
3228 /******************* General functions for the class loader *******************/
3229 /******************************************************************************/
3231 /********************* Function: loader_load ***********************************
3233 Loads and links the class desired class and each class and interface
3235 Returns: a pointer to this class
3237 *******************************************************************************/
3239 static int loader_load_running = 0;
3241 classinfo *loader_load(utf *topname)
3247 classinfo *notlinkable;
3249 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3250 pthread_mutex_lock(&compiler_mutex);
3253 /* avoid recursive calls */
3254 if (loader_load_running)
3255 return class_new(topname);
3257 loader_load_running++;
3259 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3264 starttime = getcputime();
3266 top = class_new(topname);
3269 while ((c = list_first(&unloadedclasses))) {
3270 if (!class_load(c)) {
3272 dolog("Failed to load class");
3273 list_remove(&unloadedclasses, c);
3280 dolog("Linking...");
3282 /* Added a hack to break infinite linking loops. A better
3283 * linking algorithm would be nice. -Edwin */
3285 while ((c = list_first(&unlinkedclasses))) {
3290 else if (notlinkable == c) {
3291 /* We tried to link this class for the second time and
3292 * no other classes were linked in between, so we are
3296 dolog("Cannot resolve linking dependencies");
3299 throw_linkageerror_message(c->name);
3307 dolog("Linking done.");
3310 loader_compute_subclasses();
3313 if (getloadingtime) {
3314 stoptime = getcputime();
3315 loadingtime += (stoptime - starttime);
3319 loader_load_running--;
3321 /* check if a former loader_load call tried to load/link the class and
3322 failed. This is needed because the class didn't appear in the
3323 undloadclasses or unlinkedclasses list during this class. */
3326 if (linkverbose) dolog("Failed to load class (former call)");
3327 throw_noclassdeffounderror_message(top->name);
3330 } else if (!top->linked) {
3332 dolog("Failed to link class (former call)");
3333 throw_linkageerror_message(top->name);
3338 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3342 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3343 pthread_mutex_unlock(&compiler_mutex);
3346 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3352 /****************** Function: loader_load_sysclass ****************************
3354 Loads and links the class desired class and each class and interface
3357 The pointer to the classinfo is stored in *top if top != NULL.
3358 The pointer is also returned.
3360 If the class could not be loaded the function aborts with an error.
3362 *******************************************************************************/
3364 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3368 if ((cls = loader_load(topname)) == NULL) {
3369 log_plain("Could not load important system class: ");
3370 log_plain_utf(topname);
3372 panic("Could not load important system class");
3375 if (top) *top = cls;
3381 /**************** function: create_primitive_classes ***************************
3383 create classes representing primitive types
3385 ********************************************************************************/
3388 void create_primitive_classes()
3392 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3393 /* create primitive class */
3394 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3395 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3396 c -> impldBy = NULL;
3398 /* prevent loader from loading primitive class */
3399 list_remove (&unloadedclasses, c);
3401 /* add to unlinked classes */
3402 list_addlast (&unlinkedclasses, c);
3403 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3406 primitivetype_table[i].class_primitive = c;
3408 /* create class for wrapping the primitive type */
3409 primitivetype_table[i].class_wrap =
3410 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3411 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3412 primitivetype_table[i].class_wrap -> impldBy = NULL;
3414 /* create the primitive array class */
3415 if (primitivetype_table[i].arrayname) {
3416 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3417 primitivetype_table[i].arrayclass = c;
3419 if (!c->linked) class_link(c);
3420 primitivetype_table[i].arrayvftbl = c->vftbl;
3425 /**************** function: class_primitive_from_sig ***************************
3427 return the primitive class indicated by the given signature character
3429 If the descriptor does not indicate a valid primitive type the
3430 return value is NULL.
3432 ********************************************************************************/
3434 classinfo *class_primitive_from_sig(char sig)
3437 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3438 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3439 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3440 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3441 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3442 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3443 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3444 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3445 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3450 /****************** function: class_from_descriptor ****************************
3452 return the class indicated by the given descriptor
3454 utf_ptr....first character of descriptor
3455 end_ptr....first character after the end of the string
3456 next.......if non-NULL, *next is set to the first character after
3457 the descriptor. (Undefined if an error occurs.)
3459 mode.......a combination (binary or) of the following flags:
3461 (Flags marked with * are the default settings.)
3463 What to do if a reference type descriptor is parsed successfully:
3465 CLASSLOAD_SKIP...skip it and return something != NULL
3466 * CLASSLOAD_NEW....get classinfo * via class_new
3467 CLASSLOAD_LOAD...get classinfo * via loader_load
3469 How to handle primitive types:
3471 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3472 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3474 How to handle "V" descriptors:
3476 * CLASSLOAD_VOID.....handle it like other primitive types
3477 CLASSLOAD_NOVOID...treat it as an error
3479 How to deal with extra characters after the end of the
3482 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3483 CLASSLOAD_CHECKEND.....treat them as an error
3485 How to deal with errors:
3487 * CLASSLOAD_PANIC....abort execution with an error message
3488 CLASSLOAD_NOPANIC..return NULL on error
3490 ********************************************************************************/
3492 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3493 char **next, int mode)
3495 char *start = utf_ptr;
3499 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3501 if (mode & CLASSLOAD_CHECKEND)
3502 error |= (utf_ptr != end_ptr);
3505 if (next) *next = utf_ptr;
3509 if (mode & CLASSLOAD_NOVOID)
3520 return (mode & CLASSLOAD_NULLPRIMITIVE)
3522 : class_primitive_from_sig(*start);
3529 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3530 name = utf_new(start,utf_ptr-start);
3531 return (mode & CLASSLOAD_LOAD)
3532 ? loader_load(name) : class_new(name); /* XXX handle errors */
3536 /* An error occurred */
3537 if (mode & CLASSLOAD_NOPANIC)
3540 log_plain("Invalid descriptor at beginning of '");
3541 log_plain_utf(utf_new(start, end_ptr-start));
3545 panic("Invalid descriptor");
3547 /* keep compiler happy */
3552 /******************* function: type_from_descriptor ****************************
3554 return the basic type indicated by the given descriptor
3556 This function parses a descriptor and returns its basic type as
3557 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3559 cls...if non-NULL the referenced variable is set to the classinfo *
3560 returned by class_from_descriptor.
3562 For documentation of the arguments utf_ptr, end_ptr, next and mode
3563 see class_from_descriptor. The only difference is that
3564 type_from_descriptor always uses CLASSLOAD_PANIC.
3566 ********************************************************************************/
3568 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3569 char **next, int mode)
3572 if (!cls) cls = &mycls;
3573 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3590 return TYPE_ADDRESS;
3595 /*************** function: create_system_exception_classes *******************************
3597 create system exception classes needed by default
3599 ********************************************************************************/
3601 static void create_system_exception_classes()
3604 if (verbose) log_text("loader_init: create_system_exception_classs: loader_load: java/lang/ClassCastException");
3605 loader_load_sysclass(&class_java_lang_ClassCastException,
3606 utf_new_char ("java/lang/ClassCastException"));
3607 loader_load_sysclass(&class_java_lang_NullPointerException,
3608 utf_new_char ("java/lang/NullPointerException"));
3609 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3610 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3611 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3612 utf_new_char ("java/lang/NegativeArraySizeException"));
3613 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3614 utf_new_char ("java/lang/OutOfMemoryError"));
3615 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3616 utf_new_char ("java/lang/ArrayStoreException"));
3617 loader_load_sysclass(&class_java_lang_ArithmeticException,
3618 utf_new_char ("java/lang/ArithmeticException"));
3619 loader_load_sysclass(&class_java_lang_ThreadDeath,
3620 utf_new_char ("java/lang/ThreadDeath"));
3626 /*************** function: create_system_exception_classes *******************************
3628 create system exception proto classes needed by default
3630 ********************************************************************************/
3632 static void create_system_exception_proto_classes()
3635 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3636 proto_java_lang_ClassCastException =
3637 builtin_new(class_java_lang_ClassCastException);
3639 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3641 proto_java_lang_NullPointerException =
3642 builtin_new(class_java_lang_NullPointerException);
3643 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3645 proto_java_lang_ArrayIndexOutOfBoundsException =
3646 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3648 proto_java_lang_NegativeArraySizeException =
3649 builtin_new(class_java_lang_NegativeArraySizeException);
3651 proto_java_lang_OutOfMemoryError =
3652 builtin_new(class_java_lang_OutOfMemoryError);
3654 proto_java_lang_ArithmeticException =
3655 builtin_new(class_java_lang_ArithmeticException);
3657 proto_java_lang_ArrayStoreException =
3658 builtin_new(class_java_lang_ArrayStoreException);
3660 proto_java_lang_ThreadDeath =
3661 builtin_new(class_java_lang_ThreadDeath);
3668 /*************** function: create_pseudo_classes *******************************
3670 create pseudo classes used by the typechecker
3672 ********************************************************************************/
3674 static void create_pseudo_classes()
3676 /* pseudo class for Arraystubs (extends java.lang.Object) */
3678 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3679 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3681 pseudo_class_Arraystub->super = class_java_lang_Object;
3682 pseudo_class_Arraystub->interfacescount = 2;
3683 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3684 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3685 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3687 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3688 class_link(pseudo_class_Arraystub);
3690 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3692 /* pseudo class representing the null type */
3694 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3695 list_remove(&unloadedclasses, pseudo_class_Null);
3697 pseudo_class_Null->super = class_java_lang_Object;
3699 list_addlast(&unlinkedclasses, pseudo_class_Null);
3700 class_link(pseudo_class_Null);
3702 /* pseudo class representing new uninitialized objects */
3704 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3705 list_remove(&unloadedclasses, pseudo_class_New);
3707 pseudo_class_New->super = class_java_lang_Object;
3709 list_addlast(&unlinkedclasses, pseudo_class_New);
3710 class_link(pseudo_class_New);
3714 /********************** Function: loader_init **********************************
3716 Initializes all lists and loads all classes required for the system or the
3719 *******************************************************************************/
3721 void loader_init(u1 *stackbottom)
3725 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3726 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3727 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3729 /* create utf-symbols for pointer comparison of frequently used strings */
3730 utf_innerclasses = utf_new_char("InnerClasses");
3731 utf_constantvalue = utf_new_char("ConstantValue");
3732 utf_code = utf_new_char("Code");
3733 utf_finalize = utf_new_char("finalize");
3734 utf_fidesc = utf_new_char("()V");
3735 utf_init = utf_new_char("<init>");
3736 utf_clinit = utf_new_char("<clinit>");
3737 utf_initsystemclass = utf_new_char("initializeSystemClass");
3738 utf_systemclass = utf_new_char("java/lang/System");
3739 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3740 utf_initialize = utf_new_char("initialize");
3741 utf_initializedesc = utf_new_char("(I)V");
3743 utf_vmclass = utf_new_char("java/lang/VMClass");
3744 utf_java_lang_Object= utf_new_char("java/lang/Object");
3746 array_packagename = utf_new_char("<the array package>");
3748 /* create some important classes */
3749 /* These classes have to be created now because the classinfo
3750 * pointers are used in the loading code.
3752 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3753 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3754 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3755 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3757 if (verbose) log_text("loader_init: java/lang/Object");
3758 /* load the classes which were created above */
3759 loader_load_sysclass(NULL, class_java_lang_Object->name);
3761 loader_inited = 1; /*JOWENN*/
3763 loader_load_sysclass(&class_java_lang_Throwable,
3764 utf_new_char("java/lang/Throwable"));
3766 create_system_exception_classes();
3768 /* create classes representing primitive types */
3769 create_primitive_classes();
3771 /* create classes used by the typechecker */
3772 create_pseudo_classes();
3774 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3775 stringtable_update();
3777 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3781 create_system_exception_proto_classes();
3787 /********************* Function: loader_initclasses ****************************
3789 Initializes all loaded but uninitialized classes
3791 *******************************************************************************/
3794 /* XXX TWISTI: i think we do not need this */
3795 void loader_initclasses ()
3799 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3800 pthread_mutex_lock(&compiler_mutex);
3803 intsDisable(); /* schani */
3805 if (makeinitializations) {
3806 c = list_first(&linkedclasses);
3809 c = list_next(&linkedclasses, c);
3813 intsRestore(); /* schani */
3815 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3816 pthread_mutex_unlock(&compiler_mutex);
3822 static void loader_compute_class_values(classinfo *c)
3826 c->vftbl->baseval = ++classvalue;
3829 while (subs != NULL) {
3830 loader_compute_class_values(subs);
3831 subs = subs->nextsub;
3833 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3838 for (i = 0; i < c->index; i++)
3840 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3841 utf_display(c->name);
3848 void loader_compute_subclasses()
3852 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3853 intsDisable(); /* schani */
3856 c = list_first(&linkedclasses);
3858 if (!(c->flags & ACC_INTERFACE)) {
3862 c = list_next(&linkedclasses, c);
3865 c = list_first(&linkedclasses);
3867 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3868 c->nextsub = c->super->sub;
3871 c = list_next(&linkedclasses, c);
3875 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3878 loader_compute_class_values(class_java_lang_Object);
3879 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3883 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3884 intsRestore(); /* schani */
3889 /******************** function classloader_buffer ******************************
3891 sets buffer for reading classdata
3893 *******************************************************************************/
3895 void classload_buffer(u1 *buf, int len)
3898 classbuffer_size = len;
3899 classbuf_pos = buf - 1;
3903 /******************** Function: loader_close ***********************************
3907 *******************************************************************************/
3913 while ((c = list_first(&unloadedclasses))) {
3914 list_remove(&unloadedclasses, c);
3917 while ((c = list_first(&unlinkedclasses))) {
3918 list_remove(&unlinkedclasses, c);
3921 while ((c = list_first(&linkedclasses))) {
3922 list_remove(&linkedclasses, c);
3929 * These are local overrides for various environment variables in Emacs.
3930 * Please do not remove this and leave it at the end of the file, where
3931 * Emacs will automagically detect them.
3932 * ---------------------------------------------------------------------
3935 * indent-tabs-mode: t