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 911 2004-02-04 11:42:41Z carolyn $
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 | ACC_SUPER)) != 0)
1727 panic("Interface class has invalid flags");
1729 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1730 panic("Class is declared both abstract and final");
1734 if (class_getconstant(c, i, CONSTANT_Class) != c)
1735 panic("Invalid this_class in class file");
1737 /* retrieve superclass */
1738 if ((i = suck_u2())) {
1739 c->super = class_getconstant(c, i, CONSTANT_Class);
1741 /* java.lang.Object may not have a super class. */
1742 if (c->name == utf_java_lang_Object)
1743 panic("java.lang.Object with super class");
1745 /* Interfaces must have j.l.O as super class. */
1746 if ((c->flags & ACC_INTERFACE) != 0
1747 && c->super->name != utf_java_lang_Object)
1749 panic("Interface with super class other than java.lang.Object");
1754 /* This is only allowed for java.lang.Object. */
1755 if (c->name != utf_java_lang_Object)
1756 panic("Class (not java.lang.Object) without super class");
1759 /* retrieve interfaces */
1760 c->interfacescount = suck_u2();
1761 c->interfaces = MNEW(classinfo*, c->interfacescount);
1762 for (i = 0; i < c->interfacescount; i++) {
1764 class_getconstant(c, suck_u2(), CONSTANT_Class);
1768 c->fieldscount = suck_u2();
1769 /* utf_display(c->name);
1770 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1772 c->fields = GCNEW(fieldinfo, c->fieldscount);
1773 for (i = 0; i < c->fieldscount; i++) {
1774 field_load(&(c->fields[i]), c);
1778 c->methodscount = suck_u2();
1779 c->methods = MNEW(methodinfo, c->methodscount);
1780 for (i = 0; i < c->methodscount; i++) {
1781 method_load(&(c->methods[i]), c);
1784 /* Check if all fields and methods can be uniquely
1785 * identified by (name,descriptor). */
1787 /* We use a hash table here to avoid making the
1788 * average case quadratic in # of methods, fields.
1790 static int shift = 0;
1792 u2 *next; /* for chaining colliding hash entries */
1798 /* Allocate hashtable */
1799 len = c->methodscount;
1800 if (len < c->fieldscount) len = c->fieldscount;
1802 hashtab = MNEW(u2,(hashlen + len));
1803 next = hashtab + hashlen;
1805 /* Determine bitshift (to get good hash values) */
1815 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1816 for (i = 0; i<c->fieldscount; ++i) {
1817 fieldinfo *fi = c->fields + i;
1818 /* It's ok if we lose bits here */
1819 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1821 if ((old = hashtab[index]) != 0) {
1823 /* dolog("HASHHIT %d --> %d",index,old); */
1826 /* dolog("HASHCHECK %d",old); */
1827 if (c->fields[old].name == fi->name
1828 && c->fields[old].descriptor == fi->descriptor)
1830 dolog("Duplicate field (%d,%d):",i,old);
1831 log_utf(fi->name); log_utf(fi->descriptor);
1832 panic("Fields with same name and descriptor");
1834 } while ((old = next[old]) != 0);
1836 /* else dolog("HASHLUCKY"); */
1837 hashtab[index] = i+1;
1841 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1842 for (i = 0; i<c->methodscount; ++i) {
1843 methodinfo *mi = c->methods + i;
1844 /* It's ok if we lose bits here */
1845 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1847 if ((old = hashtab[index]) != 0) {
1849 /* dolog("HASHHIT %d --> %d",index,old); */
1852 /* dolog("HASHCHECK %d",old); */
1853 if (c->methods[old].name == mi->name
1854 && c->methods[old].descriptor == mi->descriptor)
1856 dolog("Duplicate method (%d,%d):",i,old);
1857 log_utf(mi->name); log_utf(mi->descriptor);
1858 panic("Methods with same name and descriptor");
1860 } while ((old = next[old]) != 0);
1862 /* else dolog("HASHLUCKY"); */
1863 hashtab[index] = i+1;
1866 MFREE(hashtab,u2,(hashlen + len));
1870 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1871 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1872 count_class_infos += sizeof(methodinfo) * c->methodscount;
1875 /* load variable-length attribute structures */
1876 attribute_load(suck_u2(), c);
1881 /* remove class from list of unloaded classes and
1882 add to list of unlinked classes */
1883 list_remove(&unloadedclasses, c);
1884 list_addlast(&unlinkedclasses, c);
1893 /************** internal Function: class_highestinterface ***********************
1895 Used by the function class_link to determine the amount of memory needed
1896 for the interface table.
1898 *******************************************************************************/
1900 static s4 class_highestinterface(classinfo *c)
1905 if (!(c->flags & ACC_INTERFACE)) {
1906 char logtext[MAXLOGTEXT];
1907 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1908 utf_sprint(logtext + strlen(logtext), c->name);
1909 error("%s",logtext);
1913 for (i = 0; i < c->interfacescount; i++) {
1914 s4 h2 = class_highestinterface(c->interfaces[i]);
1922 /* class_addinterface **********************************************************
1924 Is needed by class_link for adding a VTBL to a class. All interfaces
1925 implemented by ic are added as well.
1927 *******************************************************************************/
1929 static void class_addinterface (classinfo *c, classinfo *ic)
1933 vftbl *vftbl = c->vftbl;
1935 if (i >= vftbl->interfacetablelength)
1936 panic ("Inernal error: interfacetable overflow");
1937 if (vftbl->interfacetable[-i])
1940 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1941 vftbl->interfacevftbllength[i] = 1;
1942 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1943 vftbl->interfacetable[-i][0] = NULL;
1946 vftbl->interfacevftbllength[i] = ic->methodscount;
1947 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1950 count_vftbl_len += sizeof(methodptr) *
1951 (ic->methodscount + (ic->methodscount == 0));
1954 for (j=0; j<ic->methodscount; j++) {
1957 for (m = 0; m < sc->methodscount; m++) {
1958 methodinfo *mi = &(sc->methods[m]);
1959 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1960 vftbl->interfacetable[-i][j] =
1961 vftbl->table[mi->vftblindex];
1971 for (j = 0; j < ic->interfacescount; j++)
1972 class_addinterface(c, ic->interfaces[j]);
1976 /******************* Function: class_new_array *********************************
1978 This function is called by class_new to setup an array class.
1980 *******************************************************************************/
1982 void class_new_array(classinfo *c)
1984 classinfo *comp = NULL;
1988 /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
1990 /* Array classes are not loaded from classfiles. */
1991 list_remove(&unloadedclasses, c);
1993 /* Check array class name */
1994 namelen = c->name->blength;
1995 if (namelen < 2 || c->name->text[0] != '[')
1996 panic("Invalid array class name");
1998 /* Check the component type */
1999 switch (c->name->text[1]) {
2001 /* c is an array of arrays. We have to create the component class. */
2002 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
2006 /* c is an array of objects. */
2007 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2008 panic("Invalid array class name");
2009 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2013 /* Setup the array class */
2014 c->super = class_java_lang_Object;
2015 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2017 c->interfacescount = 2;
2018 c->interfaces = MNEW(classinfo*,2);
2019 c->interfaces[0] = class_java_lang_Cloneable;
2020 c->interfaces[1] = class_java_io_Serializable;
2022 c->methodscount = 1;
2023 c->methods = MNEW (methodinfo, c->methodscount);
2026 memset(clone, 0, sizeof(methodinfo));
2027 clone->flags = ACC_PUBLIC;
2028 clone->name = utf_new_char("clone");
2029 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2031 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2032 clone->monoPoly = MONO;
2034 /* XXX: field: length? */
2036 /* The array class has to be linked */
2037 list_addlast(&unlinkedclasses,c);
2040 * Array classes which are created after the other classes have been
2041 * loaded and linked are linked explicitely.
2046 loader_load(c->name); /* XXX handle errors */
2050 /****************** Function: class_link_array *********************************
2052 This function is called by class_link to create the
2053 arraydescriptor for an array class.
2055 This function returns NULL if the array cannot be linked because
2056 the component type has not been linked yet.
2058 *******************************************************************************/
2060 static arraydescriptor *class_link_array(classinfo *c)
2062 classinfo *comp = NULL;
2063 int namelen = c->name->blength;
2064 arraydescriptor *desc;
2067 /* Check the component type */
2068 switch (c->name->text[1]) {
2070 /* c is an array of arrays. */
2071 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2072 if (!comp) panic("Could not find component array class.");
2076 /* c is an array of objects. */
2077 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2078 if (!comp) panic("Could not find component class.");
2082 /* If the component type has not been linked return NULL */
2083 if (comp && !comp->linked)
2086 /* Allocate the arraydescriptor */
2087 desc = NEW(arraydescriptor);
2090 /* c is an array of references */
2091 desc->arraytype = ARRAYTYPE_OBJECT;
2092 desc->componentsize = sizeof(void*);
2093 desc->dataoffset = OFFSET(java_objectarray,data);
2095 compvftbl = comp->vftbl;
2097 panic("Component class has no vftbl");
2098 desc->componentvftbl = compvftbl;
2100 if (compvftbl->arraydesc) {
2101 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2102 if (compvftbl->arraydesc->dimension >= 255)
2103 panic("Creating array of dimension >255");
2104 desc->dimension = compvftbl->arraydesc->dimension + 1;
2105 desc->elementtype = compvftbl->arraydesc->elementtype;
2108 desc->elementvftbl = compvftbl;
2109 desc->dimension = 1;
2110 desc->elementtype = ARRAYTYPE_OBJECT;
2114 /* c is an array of a primitive type */
2115 switch (c->name->text[1]) {
2116 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2117 desc->dataoffset = OFFSET(java_booleanarray,data);
2118 desc->componentsize = sizeof(u1);
2121 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2122 desc->dataoffset = OFFSET(java_bytearray,data);
2123 desc->componentsize = sizeof(u1);
2126 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2127 desc->dataoffset = OFFSET(java_chararray,data);
2128 desc->componentsize = sizeof(u2);
2131 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2132 desc->dataoffset = OFFSET(java_doublearray,data);
2133 desc->componentsize = sizeof(double);
2136 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2137 desc->dataoffset = OFFSET(java_floatarray,data);
2138 desc->componentsize = sizeof(float);
2141 case 'I': desc->arraytype = ARRAYTYPE_INT;
2142 desc->dataoffset = OFFSET(java_intarray,data);
2143 desc->componentsize = sizeof(s4);
2146 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2147 desc->dataoffset = OFFSET(java_longarray,data);
2148 desc->componentsize = sizeof(s8);
2151 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2152 desc->dataoffset = OFFSET(java_shortarray,data);
2153 desc->componentsize = sizeof(s2);
2157 panic("Invalid array class name");
2160 desc->componentvftbl = NULL;
2161 desc->elementvftbl = NULL;
2162 desc->dimension = 1;
2163 desc->elementtype = desc->arraytype;
2170 /********************** Function: class_link ***********************************
2172 Tries to link a class. The super class and every implemented interface must
2173 already have been linked. The function calculates the length in bytes that
2174 an instance of this class requires as well as the VTBL for methods and
2177 If the class can be linked, it is removed from the list 'unlinkedclasses'
2178 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2181 Attention: If cyclical class definitions are encountered, the program gets
2182 into an infinite loop (we'll have to work that out)
2184 *******************************************************************************/
2186 void class_link(classinfo *c)
2188 s4 supervftbllength; /* vftbllegnth of super class */
2189 s4 vftbllength; /* vftbllength of current class */
2190 s4 interfacetablelength; /* interface table length */
2191 classinfo *super = c->super; /* super class */
2192 classinfo *ic, *c2; /* intermediate class variables */
2193 vftbl *v; /* vftbl of current class */
2194 s4 i; /* interface/method/field counter */
2195 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2198 /* check if all superclasses are already linked, if not put c at end of
2199 unlinked list and return. Additionally initialize class fields. */
2201 /* check interfaces */
2203 for (i = 0; i < c->interfacescount; i++) {
2204 ic = c->interfaces[i];
2206 list_remove(&unlinkedclasses, c);
2207 list_addlast(&unlinkedclasses, c);
2210 if ((ic->flags & ACC_INTERFACE) == 0) {
2211 dolog("Specified interface is not declared as interface:");
2215 panic("Specified interface is not declared as interface");
2219 /* check super class */
2221 if (super == NULL) { /* class java.long.Object */
2223 c->classUsed = USED; /* Object class is always used CO-RT*/
2225 c->instancesize = sizeof(java_objectheader);
2227 vftbllength = supervftbllength = 0;
2229 c->finalizer = NULL;
2232 if (!super->linked) {
2233 list_remove(&unlinkedclasses, c);
2234 list_addlast(&unlinkedclasses, c);
2238 if ((super->flags & ACC_INTERFACE) != 0)
2239 panic("Interface specified as super class");
2241 /* handle array classes */
2242 /* The component class must have been linked already. */
2243 if (c->name->text[0] == '[')
2244 if ((arraydesc = class_link_array(c)) == NULL) {
2245 list_remove(&unlinkedclasses, c);
2246 list_addlast(&unlinkedclasses, c);
2250 /* Don't allow extending final classes */
2251 if ((super->flags & ACC_FINAL) != 0)
2252 panic("Trying to extend final class");
2254 if (c->flags & ACC_INTERFACE)
2255 c->index = interfaceindex++;
2257 c->index = super->index + 1;
2259 c->instancesize = super->instancesize;
2261 vftbllength = supervftbllength = super->vftbl->vftbllength;
2263 c->finalizer = super->finalizer;
2268 char logtext[MAXLOGTEXT];
2269 sprintf(logtext, "Linking Class: ");
2270 utf_sprint(logtext + strlen(logtext), c->name );
2274 /* compute vftbl length */
2276 for (i = 0; i < c->methodscount; i++) {
2277 methodinfo *m = &(c->methods[i]);
2279 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2280 classinfo *sc = super;
2283 for (j = 0; j < sc->methodscount; j++) {
2284 if (method_canoverwrite(m, &(sc->methods[j]))) {
2285 if ((sc->methods[j].flags & ACC_FINAL) != 0)
2286 panic("Trying to overwrite final method");
2287 m->vftblindex = sc->methods[j].vftblindex;
2288 goto foundvftblindex;
2293 m->vftblindex = (vftbllength++);
2299 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2302 /* compute interfacetable length */
2304 interfacetablelength = 0;
2307 for (i = 0; i < c2->interfacescount; i++) {
2308 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2309 if (h > interfacetablelength)
2310 interfacetablelength = h;
2315 /* allocate virtual function table */
2317 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2318 (vftbllength - 1) + sizeof(methodptr*) *
2319 (interfacetablelength - (interfacetablelength > 0)));
2320 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2321 (interfacetablelength > 1));
2322 c->header.vftbl = c->vftbl = v;
2324 v->vftbllength = vftbllength;
2325 v->interfacetablelength = interfacetablelength;
2326 v->arraydesc = arraydesc;
2328 /* store interface index in vftbl */
2329 if (c->flags & ACC_INTERFACE)
2330 v->baseval = -(c->index);
2332 /* copy virtual function table of super class */
2334 for (i = 0; i < supervftbllength; i++)
2335 v->table[i] = super->vftbl->table[i];
2337 /* add method stubs into virtual function table */
2339 for (i = 0; i < c->methodscount; i++) {
2340 methodinfo *m = &(c->methods[i]);
2341 if (!(m->flags & ACC_STATIC)) {
2342 v->table[m->vftblindex] = m->stubroutine;
2346 /* compute instance size and offset of each field */
2348 for (i = 0; i < c->fieldscount; i++) {
2350 fieldinfo *f = &(c->fields[i]);
2352 if (!(f->flags & ACC_STATIC) ) {
2353 dsize = desc_typesize(f->descriptor);
2354 c->instancesize = ALIGN(c->instancesize, dsize);
2355 f->offset = c->instancesize;
2356 c->instancesize += dsize;
2360 /* initialize interfacetable and interfacevftbllength */
2362 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2365 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2368 for (i = 0; i < interfacetablelength; i++) {
2369 v->interfacevftbllength[i] = 0;
2370 v->interfacetable[-i] = NULL;
2373 /* add interfaces */
2375 for (c2 = c; c2 != NULL; c2 = c2->super)
2376 for (i = 0; i < c2->interfacescount; i++) {
2377 class_addinterface(c, c2->interfaces[i]);
2380 /* add finalizer method (not for java.lang.Object) */
2382 if (super != NULL) {
2384 static utf *finame = NULL;
2385 static utf *fidesc = NULL;
2388 finame = utf_finalize;
2390 fidesc = utf_fidesc;
2392 fi = class_findmethod(c, finame, fidesc);
2394 if (!(fi->flags & ACC_STATIC)) {
2404 list_remove(&unlinkedclasses, c);
2405 list_addlast(&linkedclasses, c);
2409 /******************* Function: class_freepool **********************************
2411 Frees all resources used by this classes Constant Pool.
2413 *******************************************************************************/
2415 static void class_freecpool (classinfo *c)
2421 for (idx=0; idx < c->cpcount; idx++) {
2422 tag = c->cptags[idx];
2423 info = c->cpinfos[idx];
2427 case CONSTANT_Fieldref:
2428 case CONSTANT_Methodref:
2429 case CONSTANT_InterfaceMethodref:
2430 FREE (info, constant_FMIref);
2432 case CONSTANT_Integer:
2433 FREE (info, constant_integer);
2435 case CONSTANT_Float:
2436 FREE (info, constant_float);
2439 FREE (info, constant_long);
2441 case CONSTANT_Double:
2442 FREE (info, constant_double);
2444 case CONSTANT_NameAndType:
2445 FREE (info, constant_nameandtype);
2451 MFREE (c -> cptags, u1, c -> cpcount);
2452 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2456 /*********************** Function: class_free **********************************
2458 Frees all resources used by the class.
2460 *******************************************************************************/
2462 static void class_free(classinfo *c)
2469 MFREE(c->interfaces, classinfo*, c->interfacescount);
2471 for (i = 0; i < c->fieldscount; i++)
2472 field_free(&(c->fields[i]));
2474 for (i = 0; i < c->methodscount; i++)
2475 method_free(&(c->methods[i]));
2476 MFREE(c->methods, methodinfo, c->methodscount);
2478 if ((v = c->vftbl) != NULL) {
2480 mem_free(v->arraydesc,sizeof(arraydescriptor));
2482 for (i = 0; i < v->interfacetablelength; i++) {
2483 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2485 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2487 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2488 sizeof(methodptr*) * (v->interfacetablelength -
2489 (v->interfacetablelength > 0));
2490 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2491 (v->interfacetablelength > 1));
2495 if (c->innerclasscount)
2496 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2498 /* if (c->classvftbl)
2499 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2505 /************************* Function: class_findfield ***************************
2507 Searches a 'classinfo' structure for a field having the given name and
2510 *******************************************************************************/
2512 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2516 for (i = 0; i < c->fieldscount; i++) {
2517 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2518 return &(c->fields[i]);
2521 panic("Can not find field given in CONSTANT_Fieldref");
2523 /* keep compiler happy */
2528 /************************* Function: class_findmethod **************************
2530 Searches a 'classinfo' structure for a method having the given name and
2531 type and returns the index in the class info structure.
2532 If type is NULL, it is ignored.
2534 *******************************************************************************/
2536 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2539 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2541 int buffer_len, pos;
2543 #ifdef JOWENN_DEBUG1
2546 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2548 buffer = MNEW(char, buffer_len);
2550 strcpy(buffer, "class_findmethod: method:");
2551 utf_sprint(buffer + strlen(buffer), name);
2552 strcpy(buffer + strlen(buffer), ", desc: ");
2553 utf_sprint(buffer + strlen(buffer), desc);
2554 strcpy(buffer + strlen(buffer), ", classname: ");
2555 utf_sprint(buffer + strlen(buffer), c->name);
2559 MFREE(buffer, char, buffer_len);
2561 for (i = 0; i < c->methodscount; i++) {
2562 #ifdef JOWENN_DEBUG2
2564 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2566 buffer = MNEW(char, buffer_len);
2568 strcpy(buffer, "class_findmethod: comparing to method:");
2569 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2570 strcpy(buffer + strlen(buffer), ", desc: ");
2571 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2575 MFREE(buffer, char, buffer_len);
2579 if ((c->methods[i].name == name) && ((desc == NULL) ||
2580 (c->methods[i].descriptor == desc))) {
2585 #ifdef JOWENN_DEBUG2
2586 class_showconstantpool(c);
2587 log_text("class_findmethod: returning NULL");
2594 /************************* Function: class_findmethod **************************
2596 Searches a 'classinfo' structure for a method having the given name and
2598 If type is NULL, it is ignored.
2600 *******************************************************************************/
2602 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2606 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2608 int buffer_len, pos;
2610 #ifdef JOWENN_DEBUG1
2613 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2615 buffer = MNEW(char, buffer_len);
2617 strcpy(buffer, "class_findmethod: method:");
2618 utf_sprint(buffer + strlen(buffer), name);
2619 strcpy(buffer + strlen(buffer), ", desc: ");
2620 utf_sprint(buffer + strlen(buffer), desc);
2621 strcpy(buffer + strlen(buffer), ", classname: ");
2622 utf_sprint(buffer + strlen(buffer), c->name);
2626 MFREE(buffer, char, buffer_len);
2628 for (i = 0; i < c->methodscount; i++) {
2629 #ifdef JOWENN_DEBUG2
2631 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2633 buffer = MNEW(char, buffer_len);
2635 strcpy(buffer, "class_findmethod: comparing to method:");
2636 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2637 strcpy(buffer + strlen(buffer), ", desc: ");
2638 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2642 MFREE(buffer, char, buffer_len);
2645 if ((c->methods[i].name == name) && ((desc == NULL) ||
2646 (c->methods[i].descriptor == desc))) {
2647 return &(c->methods[i]);
2650 #ifdef JOWENN_DEBUG2
2651 class_showconstantpool(c);
2652 log_text("class_findmethod: returning NULL");
2657 s4 idx=class_findmethodIndex(c, name, desc);
2658 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2659 if (idx == -1) return NULL;
2661 return &(c->methods[idx]);
2665 /*********************** Function: class_fetchmethod **************************
2667 like class_findmethod, but aborts with an error if the method is not found
2669 *******************************************************************************/
2671 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2674 mi = class_findmethod(c, name, desc);
2677 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2678 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2679 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2680 panic("Method not found");
2687 /*********************** Function: class_findmethod_w**************************
2689 like class_findmethod, but logs a warning if the method is not found
2691 *******************************************************************************/
2693 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2696 mi = class_findmethod(c, name, desc);
2699 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2700 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2701 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2703 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2704 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2705 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2706 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2707 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2708 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2709 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2710 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2711 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2712 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2713 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2716 log_plain(" : WARNING: Method not found");log_nl( );
2723 /************************* Function: class_findmethod_approx ******************
2725 like class_findmethod but ignores the return value when comparing the
2728 *******************************************************************************/
2730 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2734 for (i = 0; i < c->methodscount; i++) {
2735 if (c->methods[i].name == name) {
2736 utf *meth_descr = c->methods[i].descriptor;
2740 return &(c->methods[i]);
2742 if (desc->blength <= meth_descr->blength) {
2743 /* current position in utf text */
2744 char *desc_utf_ptr = desc->text;
2745 char *meth_utf_ptr = meth_descr->text;
2746 /* points behind utf strings */
2747 char *desc_end = utf_end(desc);
2748 char *meth_end = utf_end(meth_descr);
2751 /* compare argument types */
2752 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2754 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2755 break; /* no match */
2758 return &(c->methods[i]); /* all parameter types equal */
2768 /***************** Function: class_resolvemethod_approx ***********************
2770 Searches a class and every super class for a method (without paying
2771 attention to the return value)
2773 *******************************************************************************/
2775 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2778 /* search for method (ignore returntype) */
2779 methodinfo *m = class_findmethod_approx(c, name, desc);
2782 /* search superclass */
2790 /************************* Function: class_resolvemethod ***********************
2792 Searches a class and every super class for a method.
2794 *******************************************************************************/
2796 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2799 methodinfo *m = class_findmethod(c, name, desc);
2801 /* search superclass */
2809 /************************* Function: class_issubclass **************************
2811 Checks if sub is a descendant of super.
2813 *******************************************************************************/
2815 bool class_issubclass(classinfo *sub, classinfo *super)
2818 if (!sub) return false;
2819 if (sub == super) return true;
2825 /****************** Initialization function for classes ******************
2827 In Java, every class can have a static initialization function. This
2828 function has to be called BEFORE calling other methods or accessing static
2831 *******************************************************************************/
2833 void class_init(classinfo *c)
2837 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2841 if (!makeinitializations)
2846 c->initialized = true;
2849 count_class_inits++;
2852 /* initialize super class */
2855 char logtext[MAXLOGTEXT];
2856 sprintf(logtext, "Initialize super class ");
2857 utf_sprint(logtext + strlen(logtext), c->super->name);
2858 sprintf(logtext + strlen(logtext), " from ");
2859 utf_sprint(logtext + strlen(logtext), c->name);
2862 class_init(c->super);
2865 /* initialize interface classes */
2866 for (i = 0; i < c->interfacescount; i++) {
2868 char logtext[MAXLOGTEXT];
2869 sprintf(logtext, "Initialize interface class ");
2870 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2871 sprintf(logtext + strlen(logtext), " from ");
2872 utf_sprint(logtext + strlen(logtext), c->name);
2875 class_init(c->interfaces[i]); /* real */
2878 m = class_findmethod(c, utf_clinit, utf_fidesc);
2881 char logtext[MAXLOGTEXT];
2882 sprintf(logtext, "Class ");
2883 utf_sprint(logtext + strlen(logtext), c->name);
2884 sprintf(logtext + strlen(logtext), " has no initializer");
2887 /* goto callinitialize;*/
2891 if (!(m->flags & ACC_STATIC))
2892 panic("Class initializer is not static!");
2895 char logtext[MAXLOGTEXT];
2896 sprintf(logtext, "Starting initializer for class: ");
2897 utf_sprint(logtext + strlen(logtext), c->name);
2901 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2906 /* now call the initializer */
2907 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2909 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2910 assert(blockInts == 0);
2914 /* we have to throw an exception */
2915 if (*exceptionptr) {
2916 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2917 printf("Caused by: ");
2918 utf_display((*exceptionptr)->vftbl->class->name);
2925 char logtext[MAXLOGTEXT];
2926 sprintf(logtext, "Finished initializer for class: ");
2927 utf_sprint(logtext + strlen(logtext), c->name);
2931 if (c->name == utf_systemclass) {
2932 /* class java.lang.System requires explicit initialization */
2935 printf("#### Initializing class System");
2937 /* find initializing method */
2938 m = class_findmethod(c,
2939 utf_initsystemclass,
2943 /* no method found */
2944 /* printf("initializeSystemClass failed"); */
2948 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2953 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2955 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2956 assert(blockInts == 0);
2960 if (*exceptionptr) {
2961 printf("#### initializeSystemClass has thrown: ");
2962 utf_display((*exceptionptr)->vftbl->class->name);
2970 /********* Function: find_class_method_constant *********/
2972 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2977 for (i=0; i<c->cpcount; i++) {
2979 e = c -> cpinfos [i];
2982 switch (c -> cptags [i]) {
2983 case CONSTANT_Methodref:
2985 constant_FMIref *fmi = e;
2986 if ( (fmi->class->name == c1)
2987 && (fmi->name == m1)
2988 && (fmi->descriptor == d1)) {
2995 case CONSTANT_InterfaceMethodref:
2997 constant_FMIref *fmi = e;
2998 if ( (fmi->class->name == c1)
2999 && (fmi->name == m1)
3000 && (fmi->descriptor == d1)) {
3014 void class_showconstanti(classinfo *c, int ii)
3020 printf ("#%d: ", (int) i);
3022 switch (c->cptags [i]) {
3023 case CONSTANT_Class:
3024 printf("Classreference -> ");
3025 utf_display(((classinfo*)e)->name);
3028 case CONSTANT_Fieldref:
3029 printf("Fieldref -> "); goto displayFMIi;
3030 case CONSTANT_Methodref:
3031 printf("Methodref -> "); goto displayFMIi;
3032 case CONSTANT_InterfaceMethodref:
3033 printf("InterfaceMethod -> "); goto displayFMIi;
3036 constant_FMIref *fmi = e;
3037 utf_display(fmi->class->name);
3039 utf_display(fmi->name);
3041 utf_display(fmi->descriptor);
3045 case CONSTANT_String:
3046 printf("String -> ");
3049 case CONSTANT_Integer:
3050 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3052 case CONSTANT_Float:
3053 printf("Float -> %f", ((constant_float*)e)->value);
3055 case CONSTANT_Double:
3056 printf("Double -> %f", ((constant_double*)e)->value);
3060 u8 v = ((constant_long*)e)->value;
3062 printf("Long -> %ld", (long int) v);
3064 printf("Long -> HI: %ld, LO: %ld\n",
3065 (long int) v.high, (long int) v.low);
3069 case CONSTANT_NameAndType:
3071 constant_nameandtype *cnt = e;
3072 printf("NameAndType: ");
3073 utf_display(cnt->name);
3075 utf_display(cnt->descriptor);
3083 panic("Invalid type of ConstantPool-Entry");
3090 void class_showconstantpool (classinfo *c)
3095 printf ("---- dump of constant pool ----\n");
3097 for (i=0; i<c->cpcount; i++) {
3098 printf ("#%d: ", (int) i);
3100 e = c -> cpinfos [i];
3103 switch (c -> cptags [i]) {
3104 case CONSTANT_Class:
3105 printf ("Classreference -> ");
3106 utf_display ( ((classinfo*)e) -> name );
3109 case CONSTANT_Fieldref:
3110 printf ("Fieldref -> "); goto displayFMI;
3111 case CONSTANT_Methodref:
3112 printf ("Methodref -> "); goto displayFMI;
3113 case CONSTANT_InterfaceMethodref:
3114 printf ("InterfaceMethod -> "); goto displayFMI;
3117 constant_FMIref *fmi = e;
3118 utf_display ( fmi->class->name );
3120 utf_display ( fmi->name);
3122 utf_display ( fmi->descriptor );
3126 case CONSTANT_String:
3127 printf ("String -> ");
3130 case CONSTANT_Integer:
3131 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3133 case CONSTANT_Float:
3134 printf ("Float -> %f", ((constant_float*)e) -> value);
3136 case CONSTANT_Double:
3137 printf ("Double -> %f", ((constant_double*)e) -> value);
3141 u8 v = ((constant_long*)e) -> value;
3143 printf ("Long -> %ld", (long int) v);
3145 printf ("Long -> HI: %ld, LO: %ld\n",
3146 (long int) v.high, (long int) v.low);
3150 case CONSTANT_NameAndType:
3152 constant_nameandtype *cnt = e;
3153 printf ("NameAndType: ");
3154 utf_display (cnt->name);
3156 utf_display (cnt->descriptor);
3160 printf ("Utf8 -> ");
3164 panic ("Invalid type of ConstantPool-Entry");
3174 /********** Function: class_showmethods (debugging only) *************/
3176 void class_showmethods (classinfo *c)
3180 printf ("--------- Fields and Methods ----------------\n");
3181 printf ("Flags: "); printflags (c->flags); printf ("\n");
3183 printf ("This: "); utf_display (c->name); printf ("\n");
3185 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3187 printf ("Index: %d\n", c->index);
3189 printf ("interfaces:\n");
3190 for (i=0; i < c-> interfacescount; i++) {
3192 utf_display (c -> interfaces[i] -> name);
3193 printf (" (%d)\n", c->interfaces[i] -> index);
3196 printf ("fields:\n");
3197 for (i=0; i < c -> fieldscount; i++) {
3198 field_display (&(c -> fields[i]));
3201 printf ("methods:\n");
3202 for (i=0; i < c -> methodscount; i++) {
3203 methodinfo *m = &(c->methods[i]);
3204 if ( !(m->flags & ACC_STATIC))
3205 printf ("vftblindex: %d ", m->vftblindex);
3207 method_display ( m );
3211 printf ("Virtual function table:\n");
3212 for (i=0; i<c->vftbl->vftbllength; i++) {
3213 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3220 /******************************************************************************/
3221 /******************* General functions for the class loader *******************/
3222 /******************************************************************************/
3224 /********************* Function: loader_load ***********************************
3226 Loads and links the class desired class and each class and interface
3228 Returns: a pointer to this class
3230 *******************************************************************************/
3232 static int loader_load_running = 0;
3234 classinfo *loader_load(utf *topname)
3240 classinfo *notlinkable;
3242 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3243 pthread_mutex_lock(&compiler_mutex);
3246 /* avoid recursive calls */
3247 if (loader_load_running)
3248 return class_new(topname);
3250 loader_load_running++;
3252 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3257 starttime = getcputime();
3259 top = class_new(topname);
3262 while ((c = list_first(&unloadedclasses))) {
3263 if (!class_load(c)) {
3265 dolog("Failed to load class");
3266 list_remove(&unloadedclasses, c);
3273 dolog("Linking...");
3275 /* Added a hack to break infinite linking loops. A better
3276 * linking algorithm would be nice. -Edwin */
3278 while ((c = list_first(&unlinkedclasses))) {
3283 else if (notlinkable == c) {
3284 /* We tried to link this class for the second time and
3285 * no other classes were linked in between, so we are
3289 dolog("Cannot resolve linking dependencies");
3292 throw_linkageerror_message(c->name);
3300 dolog("Linking done.");
3303 loader_compute_subclasses();
3306 if (getloadingtime) {
3307 stoptime = getcputime();
3308 loadingtime += (stoptime - starttime);
3312 loader_load_running--;
3314 /* check if a former loader_load call tried to load/link the class and
3315 failed. This is needed because the class didn't appear in the
3316 undloadclasses or unlinkedclasses list during this class. */
3319 if (linkverbose) dolog("Failed to load class (former call)");
3320 throw_noclassdeffounderror_message(top->name);
3323 } else if (!top->linked) {
3325 dolog("Failed to link class (former call)");
3326 throw_linkageerror_message(top->name);
3331 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3335 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3336 pthread_mutex_unlock(&compiler_mutex);
3339 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3345 /****************** Function: loader_load_sysclass ****************************
3347 Loads and links the class desired class and each class and interface
3350 The pointer to the classinfo is stored in *top if top != NULL.
3351 The pointer is also returned.
3353 If the class could not be loaded the function aborts with an error.
3355 *******************************************************************************/
3357 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3361 if ((cls = loader_load(topname)) == NULL) {
3362 log_plain("Could not load important system class: ");
3363 log_plain_utf(topname);
3365 panic("Could not load important system class");
3368 if (top) *top = cls;
3374 /**************** function: create_primitive_classes ***************************
3376 create classes representing primitive types
3378 ********************************************************************************/
3381 void create_primitive_classes()
3385 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3386 /* create primitive class */
3387 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3388 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3389 c -> impldBy = NULL;
3391 /* prevent loader from loading primitive class */
3392 list_remove (&unloadedclasses, c);
3394 /* add to unlinked classes */
3395 list_addlast (&unlinkedclasses, c);
3396 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3399 primitivetype_table[i].class_primitive = c;
3401 /* create class for wrapping the primitive type */
3402 primitivetype_table[i].class_wrap =
3403 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3404 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3405 primitivetype_table[i].class_wrap -> impldBy = NULL;
3407 /* create the primitive array class */
3408 if (primitivetype_table[i].arrayname) {
3409 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3410 primitivetype_table[i].arrayclass = c;
3412 if (!c->linked) class_link(c);
3413 primitivetype_table[i].arrayvftbl = c->vftbl;
3418 /**************** function: class_primitive_from_sig ***************************
3420 return the primitive class indicated by the given signature character
3422 If the descriptor does not indicate a valid primitive type the
3423 return value is NULL.
3425 ********************************************************************************/
3427 classinfo *class_primitive_from_sig(char sig)
3430 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3431 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3432 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3433 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3434 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3435 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3436 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3437 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3438 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3443 /****************** function: class_from_descriptor ****************************
3445 return the class indicated by the given descriptor
3447 utf_ptr....first character of descriptor
3448 end_ptr....first character after the end of the string
3449 next.......if non-NULL, *next is set to the first character after
3450 the descriptor. (Undefined if an error occurs.)
3452 mode.......a combination (binary or) of the following flags:
3454 (Flags marked with * are the default settings.)
3456 What to do if a reference type descriptor is parsed successfully:
3458 CLASSLOAD_SKIP...skip it and return something != NULL
3459 * CLASSLOAD_NEW....get classinfo * via class_new
3460 CLASSLOAD_LOAD...get classinfo * via loader_load
3462 How to handle primitive types:
3464 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3465 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3467 How to handle "V" descriptors:
3469 * CLASSLOAD_VOID.....handle it like other primitive types
3470 CLASSLOAD_NOVOID...treat it as an error
3472 How to deal with extra characters after the end of the
3475 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3476 CLASSLOAD_CHECKEND.....treat them as an error
3478 How to deal with errors:
3480 * CLASSLOAD_PANIC....abort execution with an error message
3481 CLASSLOAD_NOPANIC..return NULL on error
3483 ********************************************************************************/
3485 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3486 char **next, int mode)
3488 char *start = utf_ptr;
3492 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3494 if (mode & CLASSLOAD_CHECKEND)
3495 error |= (utf_ptr != end_ptr);
3498 if (next) *next = utf_ptr;
3502 if (mode & CLASSLOAD_NOVOID)
3513 return (mode & CLASSLOAD_NULLPRIMITIVE)
3515 : class_primitive_from_sig(*start);
3522 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3523 name = utf_new(start,utf_ptr-start);
3524 return (mode & CLASSLOAD_LOAD)
3525 ? loader_load(name) : class_new(name); /* XXX handle errors */
3529 /* An error occurred */
3530 if (mode & CLASSLOAD_NOPANIC)
3533 log_plain("Invalid descriptor at beginning of '");
3534 log_plain_utf(utf_new(start, end_ptr-start));
3538 panic("Invalid descriptor");
3540 /* keep compiler happy */
3545 /******************* function: type_from_descriptor ****************************
3547 return the basic type indicated by the given descriptor
3549 This function parses a descriptor and returns its basic type as
3550 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3552 cls...if non-NULL the referenced variable is set to the classinfo *
3553 returned by class_from_descriptor.
3555 For documentation of the arguments utf_ptr, end_ptr, next and mode
3556 see class_from_descriptor. The only difference is that
3557 type_from_descriptor always uses CLASSLOAD_PANIC.
3559 ********************************************************************************/
3561 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3562 char **next, int mode)
3565 if (!cls) cls = &mycls;
3566 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3583 return TYPE_ADDRESS;
3588 /*************** function: create_system_exception_classes *******************************
3590 create system exception classes needed by default
3592 ********************************************************************************/
3594 static void create_system_exception_classes()
3597 if (verbose) log_text("loader_init: create_system_exception_classs: loader_load: java/lang/ClassCastException");
3598 loader_load_sysclass(&class_java_lang_ClassCastException,
3599 utf_new_char ("java/lang/ClassCastException"));
3600 loader_load_sysclass(&class_java_lang_NullPointerException,
3601 utf_new_char ("java/lang/NullPointerException"));
3602 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3603 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3604 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3605 utf_new_char ("java/lang/NegativeArraySizeException"));
3606 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3607 utf_new_char ("java/lang/OutOfMemoryError"));
3608 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3609 utf_new_char ("java/lang/ArrayStoreException"));
3610 loader_load_sysclass(&class_java_lang_ArithmeticException,
3611 utf_new_char ("java/lang/ArithmeticException"));
3612 loader_load_sysclass(&class_java_lang_ThreadDeath,
3613 utf_new_char ("java/lang/ThreadDeath"));
3619 /*************** function: create_system_exception_classes *******************************
3621 create system exception proto classes needed by default
3623 ********************************************************************************/
3625 static void create_system_exception_proto_classes()
3628 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3629 proto_java_lang_ClassCastException =
3630 builtin_new(class_java_lang_ClassCastException);
3632 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3634 proto_java_lang_NullPointerException =
3635 builtin_new(class_java_lang_NullPointerException);
3636 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3638 proto_java_lang_ArrayIndexOutOfBoundsException =
3639 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3641 proto_java_lang_NegativeArraySizeException =
3642 builtin_new(class_java_lang_NegativeArraySizeException);
3644 proto_java_lang_OutOfMemoryError =
3645 builtin_new(class_java_lang_OutOfMemoryError);
3647 proto_java_lang_ArithmeticException =
3648 builtin_new(class_java_lang_ArithmeticException);
3650 proto_java_lang_ArrayStoreException =
3651 builtin_new(class_java_lang_ArrayStoreException);
3653 proto_java_lang_ThreadDeath =
3654 builtin_new(class_java_lang_ThreadDeath);
3661 /*************** function: create_pseudo_classes *******************************
3663 create pseudo classes used by the typechecker
3665 ********************************************************************************/
3667 static void create_pseudo_classes()
3669 /* pseudo class for Arraystubs (extends java.lang.Object) */
3671 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3672 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3674 pseudo_class_Arraystub->super = class_java_lang_Object;
3675 pseudo_class_Arraystub->interfacescount = 2;
3676 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3677 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3678 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3680 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3681 class_link(pseudo_class_Arraystub);
3683 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3685 /* pseudo class representing the null type */
3687 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3688 list_remove(&unloadedclasses, pseudo_class_Null);
3690 pseudo_class_Null->super = class_java_lang_Object;
3692 list_addlast(&unlinkedclasses, pseudo_class_Null);
3693 class_link(pseudo_class_Null);
3695 /* pseudo class representing new uninitialized objects */
3697 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3698 list_remove(&unloadedclasses, pseudo_class_New);
3700 pseudo_class_New->super = class_java_lang_Object;
3702 list_addlast(&unlinkedclasses, pseudo_class_New);
3703 class_link(pseudo_class_New);
3707 /********************** Function: loader_init **********************************
3709 Initializes all lists and loads all classes required for the system or the
3712 *******************************************************************************/
3714 void loader_init(u1 *stackbottom)
3718 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3719 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3720 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3722 /* create utf-symbols for pointer comparison of frequently used strings */
3723 utf_innerclasses = utf_new_char("InnerClasses");
3724 utf_constantvalue = utf_new_char("ConstantValue");
3725 utf_code = utf_new_char("Code");
3726 utf_finalize = utf_new_char("finalize");
3727 utf_fidesc = utf_new_char("()V");
3728 utf_init = utf_new_char("<init>");
3729 utf_clinit = utf_new_char("<clinit>");
3730 utf_initsystemclass = utf_new_char("initializeSystemClass");
3731 utf_systemclass = utf_new_char("java/lang/System");
3732 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3733 utf_initialize = utf_new_char("initialize");
3734 utf_initializedesc = utf_new_char("(I)V");
3736 utf_vmclass = utf_new_char("java/lang/VMClass");
3737 utf_java_lang_Object= utf_new_char("java/lang/Object");
3739 array_packagename = utf_new_char("<the array package>");
3741 /* create some important classes */
3742 /* These classes have to be created now because the classinfo
3743 * pointers are used in the loading code.
3745 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3746 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3747 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3748 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3750 if (verbose) log_text("loader_init: java/lang/Object");
3751 /* load the classes which were created above */
3752 loader_load_sysclass(NULL, class_java_lang_Object->name);
3754 loader_inited = 1; /*JOWENN*/
3756 loader_load_sysclass(&class_java_lang_Throwable,
3757 utf_new_char("java/lang/Throwable"));
3759 create_system_exception_classes();
3761 /* create classes representing primitive types */
3762 create_primitive_classes();
3764 /* create classes used by the typechecker */
3765 create_pseudo_classes();
3767 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3768 stringtable_update();
3770 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3774 create_system_exception_proto_classes();
3780 /********************* Function: loader_initclasses ****************************
3782 Initializes all loaded but uninitialized classes
3784 *******************************************************************************/
3787 /* XXX TWISTI: i think we do not need this */
3788 void loader_initclasses ()
3792 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3793 pthread_mutex_lock(&compiler_mutex);
3796 intsDisable(); /* schani */
3798 if (makeinitializations) {
3799 c = list_first(&linkedclasses);
3802 c = list_next(&linkedclasses, c);
3806 intsRestore(); /* schani */
3808 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3809 pthread_mutex_unlock(&compiler_mutex);
3815 static void loader_compute_class_values(classinfo *c)
3819 c->vftbl->baseval = ++classvalue;
3822 while (subs != NULL) {
3823 loader_compute_class_values(subs);
3824 subs = subs->nextsub;
3826 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3831 for (i = 0; i < c->index; i++)
3833 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3834 utf_display(c->name);
3841 void loader_compute_subclasses()
3845 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3846 intsDisable(); /* schani */
3849 c = list_first(&linkedclasses);
3851 if (!(c->flags & ACC_INTERFACE)) {
3855 c = list_next(&linkedclasses, c);
3858 c = list_first(&linkedclasses);
3860 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3861 c->nextsub = c->super->sub;
3864 c = list_next(&linkedclasses, c);
3868 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3871 loader_compute_class_values(class_java_lang_Object);
3872 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3876 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3877 intsRestore(); /* schani */
3882 /******************** function classloader_buffer ******************************
3884 sets buffer for reading classdata
3886 *******************************************************************************/
3888 void classload_buffer(u1 *buf, int len)
3891 classbuffer_size = len;
3892 classbuf_pos = buf - 1;
3896 /******************** Function: loader_close ***********************************
3900 *******************************************************************************/
3906 while ((c = list_first(&unloadedclasses))) {
3907 list_remove(&unloadedclasses, c);
3910 while ((c = list_first(&unlinkedclasses))) {
3911 list_remove(&unlinkedclasses, c);
3914 while ((c = list_first(&linkedclasses))) {
3915 list_remove(&linkedclasses, c);
3922 * These are local overrides for various environment variables in Emacs.
3923 * Please do not remove this and leave it at the end of the file, where
3924 * Emacs will automagically detect them.
3925 * ---------------------------------------------------------------------
3928 * indent-tabs-mode: t