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 740 2003-12-13 19:57:12Z stefan $
48 #include "toolbox/memory.h"
49 #include "toolbox/loging.h"
50 #include "threads/thread.h"
61 /* global variables ***********************************************************/
63 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
64 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
65 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
67 int count_class_infos = 0; /* variables for measurements */
68 int count_const_pool_len = 0;
69 int count_vftbl_len = 0;
70 int count_all_methods = 0;
71 int count_vmcode_len = 0;
72 int count_extable_len = 0;
73 int count_class_loads = 0;
74 int count_class_inits = 0;
76 bool loadverbose = false; /* switches for debug messages */
77 bool linkverbose = false;
78 bool initverbose = false;
80 bool makeinitializations = true;
82 bool getloadingtime = false; /* to measure the runtime */
83 long int loadingtime = 0;
85 static s4 interfaceindex; /* sequential numbering of interfaces */
87 list unloadedclasses; /* list of all referenced but not loaded classes */
88 list unlinkedclasses; /* list of all loaded but not linked classes */
89 list linkedclasses; /* list of all completely linked classes */
92 /* utf-symbols for pointer comparison of frequently used strings */
94 static utf *utf_innerclasses; /* InnerClasses */
95 static utf *utf_constantvalue; /* ConstantValue */
96 static utf *utf_code; /* Code */
97 static utf *utf_finalize; /* finalize */
98 static utf *utf_fidesc; /* ()V changed */
99 static utf *utf_clinit; /* <clinit> */
100 static utf *utf_initsystemclass; /* initializeSystemClass */
101 static utf *utf_systemclass; /* java/lang/System */
102 static utf *utf_vmclassloader; /*java/lang/VMClassLoader*/
103 static utf *utf_vmclass; /*java/lang/VMClassLoader*/
104 static utf *utf_initialize;
105 static utf *utf_initializedesc;
109 static unzFile uf = 0;
119 /* important system classes ***************************************************/
121 classinfo *class_java_lang_Object;
122 classinfo *class_java_lang_String;
124 classinfo *class_java_lang_Throwable;
125 classinfo *class_java_lang_Cloneable;
126 classinfo *class_java_io_Serializable;
128 /* Pseudo classes for the typechecker */
129 classinfo *pseudo_class_Arraystub = NULL;
130 classinfo *pseudo_class_Null = NULL;
131 classinfo *pseudo_class_New = NULL;
132 vftbl *pseudo_class_Arraystub_vftbl = NULL;
135 /* These are made static so they cannot be used for throwing in native */
137 static classinfo *class_java_lang_ClassCastException;
138 static classinfo *class_java_lang_NullPointerException;
139 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
140 static classinfo *class_java_lang_NegativeArraySizeException;
141 static classinfo *class_java_lang_OutOfMemoryError;
142 static classinfo *class_java_lang_ArithmeticException;
143 static classinfo *class_java_lang_ArrayStoreException;
144 static classinfo *class_java_lang_ThreadDeath;
146 static methodinfo method_clone_array;
148 static int loader_inited = 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 }};
172 /* instances of important system classes **************************************/
174 java_objectheader *proto_java_lang_ClassCastException;
175 java_objectheader *proto_java_lang_NullPointerException;
176 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
177 java_objectheader *proto_java_lang_NegativeArraySizeException;
178 java_objectheader *proto_java_lang_OutOfMemoryError;
179 java_objectheader *proto_java_lang_ArithmeticException;
180 java_objectheader *proto_java_lang_ArrayStoreException;
181 java_objectheader *proto_java_lang_ThreadDeath;
183 /************* functions for reading classdata *********************************
185 getting classdata in blocks of variable size
186 (8,16,32,64-bit integer or float)
188 *******************************************************************************/
190 static char *classpath = ""; /* searchpath for classfiles */
191 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
192 static u1 *classbuf_pos; /* current position in classfile buffer */
193 static int classbuffer_size; /* size of classfile-data */
195 /* assert that at least <len> bytes are left to read */
196 /* <len> is limited to the range of non-negative s4 values */
197 #define ASSERT_LEFT(len) \
198 do {if ( ((s4)(len)) < 0 \
199 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
200 panic("Unexpected end of classfile"); } while(0)
202 /* transfer block of classfile data into a buffer */
204 #define suck_nbytes(buffer,len) \
205 do {ASSERT_LEFT(len); \
206 memcpy(buffer,classbuf_pos+1,len); \
207 classbuf_pos+=len;} while (0)
209 /* skip block of classfile data */
211 #define skip_nbytes(len) \
212 do {ASSERT_LEFT(len); \
213 classbuf_pos+=len;} while(0)
218 return *++classbuf_pos;
222 u1 a=suck_u1(), b=suck_u1();
223 return ((u2)a<<8)+(u2)b;
227 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
228 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
230 #define suck_s8() (s8) suck_u8()
231 #define suck_s2() (s2) suck_u2()
232 #define suck_s4() (s4) suck_u4()
233 #define suck_s1() (s1) suck_u1()
236 /* get u8 from classfile data */
243 return (hi << 32) + lo;
253 /* get float from classfile data */
254 static float suck_float()
261 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
262 memcpy((u1*) (&f), buffer, 4);
264 suck_nbytes((u1*) (&f), 4);
267 PANICIF (sizeof(float) != 4, "Incompatible float-format");
273 /* get double from classfile data */
274 static double suck_double()
281 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
282 memcpy((u1*) (&d), buffer, 8);
284 suck_nbytes((u1*) (&d), 8);
287 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
293 /************************** function suck_init *********************************
295 called once at startup, sets the searchpath for the classfiles
297 *******************************************************************************/
299 void suck_init(char *cpath)
306 /************************** function suck_start ********************************
308 returns true if classbuffer is already loaded or a file for the
309 specified class has succussfully been read in. All directories of
310 the searchpath are used to find the classfile (<classname>.class).
311 Returns false if no classfile is found and writes an error message.
313 *******************************************************************************/
315 bool suck_start(utf *classname)
318 #define MAXFILENAME 1000 /* maximum length of a filename */
320 char filename[MAXFILENAME+10]; /* room for '.class' */
321 char *pathpos; /* position in searchpath */
322 char c, *utf_ptr; /* pointer to the next utf8-character */
324 int filenamelen, err;
328 if (classbuffer) /* classbuffer is already valid */
335 /* skip path separator */
337 while (*pathpos == ':')
340 /* extract directory from searchpath */
343 while ((*pathpos) && (*pathpos != ':')) {
344 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
345 filename[filenamelen++] = *(pathpos++);
349 if (filenamelen > 4) {
350 if ( ((filename[filenamelen - 1] == 'p') || (filename[filenamelen - 1] == 'P')) &
351 ((filename[filenamelen - 2] == 'i') || (filename[filenamelen - 2] == 'I')) &
352 ((filename[filenamelen - 3] == 'z') || (filename[filenamelen - 3] == 'Z')) ) {
359 filename[filenamelen++] = '\0';
360 if (uf == 0) uf = unzOpen(filename);
362 utf_ptr = classname->text;
364 while (utf_ptr < utf_end(classname)) {
365 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
367 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
369 filename[filenamelen++] = c;
371 strcpy(filename + filenamelen, ".class");
372 if (cacao_locate(uf,classname) == UNZ_OK) {
373 unz_file_info file_info;
374 log_text("Class found in zip file");
375 if (unzGetCurrentFileInfo(uf, &file_info, filename,
376 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
377 if (unzOpenCurrentFile(uf) == UNZ_OK) {
378 classbuffer_size = file_info.uncompressed_size;
379 classbuffer = MNEW(u1, classbuffer_size);
380 classbuf_pos = classbuffer - 1;
381 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
382 if (unzReadCurrentFile(uf, classbuffer, classbuffer_size) == classbuffer_size) {
383 unzCloseCurrentFile(uf);
386 MFREE(classbuffer, u1, classbuffer_size);
387 log_text("Error while unzipping");
389 } else log_text("Error while opening file in archive");
390 } else log_text("Error while retrieving fileinfo");
392 unzCloseCurrentFile(uf);
397 filename[filenamelen++] = '/';
399 /* add classname to filename */
401 utf_ptr = classname->text;
402 while (utf_ptr < utf_end(classname)) {
403 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
405 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
407 filename[filenamelen++] = c;
412 strcpy(filename + filenamelen, ".class");
414 classfile = fopen(filename, "r");
415 if (classfile) { /* file exists */
417 /* determine size of classfile */
419 /* dolog("File: %s",filename); */
421 err = stat(filename, &buffer);
423 if (!err) { /* read classfile data */
424 classbuffer_size = buffer.st_size;
425 classbuffer = MNEW(u1, classbuffer_size);
426 classbuf_pos = classbuffer - 1;
427 fread(classbuffer, 1, classbuffer_size, classfile);
435 dolog("Warning: Can not open class file '%s'", filename);
442 /************************** function suck_stop *********************************
444 frees memory for buffer with classfile data.
445 Caution: this function may only be called if buffer has been allocated
446 by suck_start with reading a file
448 *******************************************************************************/
452 /* determine amount of classdata not retrieved by suck-operations */
454 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
456 if (classdata_left > 0) {
458 dolog("There are %d access bytes at end of classfile",
465 MFREE(classbuffer, u1, classbuffer_size);
470 /******************************************************************************/
471 /******************* Some support functions ***********************************/
472 /******************************************************************************/
476 void fprintflags (FILE *fp, u2 f)
478 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
479 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
480 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
481 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
482 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
483 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
484 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
485 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
486 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
487 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
488 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
491 /********** internal function: printflags (only for debugging) ***************/
492 void printflags (u2 f)
494 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
495 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
496 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
497 if ( f & ACC_STATIC ) printf (" STATIC");
498 if ( f & ACC_FINAL ) printf (" FINAL");
499 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
500 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
501 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
502 if ( f & ACC_NATIVE ) printf (" NATIVE");
503 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
504 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
508 /************************* Function: skipattribute *****************************
510 skips a (1) 'attribute' structure in the class file
512 *******************************************************************************/
514 static void skipattribute ()
522 /********************** Function: skipattributebody ****************************
524 skips an attribute after the 16 bit reference to attribute_name has already
527 *******************************************************************************/
529 static void skipattributebody ()
536 /************************* Function: skipattributes ****************************
538 skips num attribute structures
540 *******************************************************************************/
542 static void skipattributes (u4 num)
545 for (i = 0; i < num; i++)
549 /******************** function: innerclass_getconstant ************************
551 like class_getconstant, but if cptags is ZERO null is returned
553 *******************************************************************************/
555 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
557 /* invalid position in constantpool */
558 if (pos >= c->cpcount)
559 panic ("Attempt to access constant outside range");
561 /* constantpool entry of type 0 */
565 /* check type of constantpool entry */
566 if (c->cptags[pos] != ctype) {
567 error ("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
568 (int) ctype, (int) c->cptags[pos] );
571 return c->cpinfos[pos];
574 /************************ function: attribute_load ****************************
576 read attributes from classfile
578 *******************************************************************************/
580 static void attribute_load (u4 num, classinfo *c)
584 for (i = 0; i < num; i++) {
585 /* retrieve attribute name */
586 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
588 if ( aname == utf_innerclasses) {
589 /* innerclasses attribute */
591 /* skip attribute length */
593 /* number of records */
594 c->innerclasscount = suck_u2();
595 /* allocate memory for innerclass structure */
596 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
598 for (j=0;j<c->innerclasscount;j++) {
600 /* The innerclass structure contains a class with an encoded name,
601 its defining scope, its simple name and a bitmask of the access flags.
602 If an inner class is not a member, its outer_class is NULL,
603 if a class is anonymous, its name is NULL. */
605 innerclassinfo *info = c->innerclass + j;
607 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
608 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
609 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
610 info->flags = suck_u2 (); /* access_flags bitmask */
613 /* unknown attribute */
614 skipattributebody ();
619 /******************* function: checkfielddescriptor ****************************
621 checks whether a field-descriptor is valid and aborts otherwise
622 all referenced classes are inserted into the list of unloaded classes
624 *******************************************************************************/
626 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
628 class_from_descriptor(utf_ptr,end_pos,NULL,
630 | CLASSLOAD_NULLPRIMITIVE
632 | CLASSLOAD_CHECKEND);
634 char *tstart; /* pointer to start of classname */
636 char *start = utf_ptr;
638 switch (*utf_ptr++) {
652 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
653 panic ("Ill formed descriptor");
657 panic ("Ill formed descriptor");
660 /* exceeding characters */
661 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
666 /******************* function checkmethoddescriptor ****************************
668 checks whether a method-descriptor is valid and aborts otherwise.
669 All referenced classes are inserted into the list of unloaded classes.
671 *******************************************************************************/
673 static void checkmethoddescriptor (utf *d)
675 char *utf_ptr = d->text; /* current position in utf text */
676 char *end_pos = utf_end(d); /* points behind utf string */
678 /* method descriptor must start with parenthesis */
679 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
681 /* check arguments */
682 while (utf_ptr != end_pos && *utf_ptr != ')') {
683 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
685 | CLASSLOAD_NULLPRIMITIVE
689 if (utf_ptr == end_pos) panic("Missing return type in method descriptor");
690 utf_ptr++; /* skip ')' */
692 class_from_descriptor(utf_ptr,end_pos,NULL,
694 | CLASSLOAD_NULLPRIMITIVE
695 | CLASSLOAD_CHECKEND);
698 /* XXX check length */
699 /* check arguments */
700 while ((c = *utf_ptr++) != ')') {
717 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
718 panic ("Ill formed method descriptor");
722 panic ("Ill formed methodtype-descriptor");
726 /* check returntype */
728 /* returntype void */
729 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
732 /* treat as field-descriptor */
733 checkfielddescriptor (utf_ptr,end_pos);
737 /***************** Function: print_arraydescriptor ****************************
739 Debugging helper for displaying an arraydescriptor
741 *******************************************************************************/
744 print_arraydescriptor(FILE *file,arraydescriptor *desc)
747 fprintf(file,"<NULL>");
752 if (desc->componentvftbl) {
753 if (desc->componentvftbl->class)
754 utf_fprint(file,desc->componentvftbl->class->name);
756 fprintf(file,"<no classinfo>");
762 if (desc->elementvftbl) {
763 if (desc->elementvftbl->class)
764 utf_fprint(file,desc->elementvftbl->class->name);
766 fprintf(file,"<no classinfo>");
770 fprintf(file,",%d,%d,%d,%d}",desc->arraytype,desc->dimension,
771 desc->dataoffset,desc->componentsize);
774 /******************************************************************************/
775 /************************** Functions for fields ****************************/
776 /******************************************************************************/
779 /************************ Function: field_load *********************************
781 Load everything about a class field from the class file and fill a
782 'fieldinfo' structure. For static fields, space in the data segment is
785 *******************************************************************************/
787 static void field_load (fieldinfo *f, classinfo *c)
792 f -> flags = suck_u2 (); /* ACC flags */
793 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
794 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
795 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
796 f -> offset = 0; /* offset from start of object */
801 case TYPE_INT: f->value.i = 0; break;
802 case TYPE_FLOAT: f->value.f = 0.0; break;
803 case TYPE_DOUBLE: f->value.d = 0.0; break;
804 case TYPE_ADDRESS: f->value.a = NULL;
805 heap_addreference (&(f->value.a)); /* make global reference (GC) */
809 f->value.l = 0; break;
811 f->value.l.low = 0; f->value.l.high = 0; break;
815 /* read attributes */
817 for (i=0; i<attrnum; i++) {
821 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
823 if ( aname != utf_constantvalue ) {
824 /* unknown attribute */
825 skipattributebody ();
828 /* constant value attribute */
830 /* skip attribute length */
832 /* index of value in constantpool */
835 /* initialize field with value from constantpool */
838 constant_integer *ci =
839 class_getconstant(c, pindex, CONSTANT_Integer);
840 f->value.i = ci -> value;
846 class_getconstant(c, pindex, CONSTANT_Long);
848 f->value.l = cl -> value;
854 class_getconstant(c, pindex, CONSTANT_Float);
856 f->value.f = cf->value;
861 constant_double *cd =
862 class_getconstant(c, pindex, CONSTANT_Double);
864 f->value.d = cd->value;
869 utf *u = class_getconstant(c, pindex, CONSTANT_String);
870 /* create javastring from compressed utf8-string */
871 f->value.a = literalstring_new(u);
876 log_text ("Invalid Constant - Type");
885 /********************** function: field_free **********************************/
887 static void field_free (fieldinfo *f)
893 /**************** Function: field_display (debugging only) ********************/
895 void field_display (fieldinfo *f)
898 printflags (f -> flags);
900 utf_display (f -> name);
902 utf_display (f -> descriptor);
903 printf (" offset: %ld\n", (long int) (f -> offset) );
907 /******************************************************************************/
908 /************************* Functions for methods ******************************/
909 /******************************************************************************/
912 /*********************** Function: method_load *********************************
914 Loads a method from the class file and fills an existing 'methodinfo'
915 structure. For native methods, the function pointer field is set to the
916 real function pointer, for JavaVM methods a pointer to the compiler is used
919 *******************************************************************************/
921 static void method_load (methodinfo *m, classinfo *c)
931 m -> flags = suck_u2 ();
932 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
933 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
934 checkmethoddescriptor(m->descriptor);
937 m -> exceptiontable = NULL;
938 m -> entrypoint = NULL;
940 m -> stubroutine = NULL;
941 m -> methodUsed = NOTUSED;
942 m -> monoPoly = MONO;
944 m -> subRedefsUsed = 0;
948 if (! (m->flags & ACC_NATIVE) ) {
949 m -> stubroutine = createcompilerstub (m);
953 functionptr f = native_findfunction
954 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
956 m -> stubroutine = createnativestub (f, m);
962 for (i=0; i<attrnum; i++) {
965 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
967 if ( aname != utf_code) {
968 skipattributebody ();
972 if (m -> jcode) panic ("Two code-attributes for one method!");
975 m -> maxstack = suck_u2();
976 m -> maxlocals = suck_u2();
979 panic("bytecode has zero length");
981 panic("bytecode too long");
982 m -> jcodelength = codelen;
983 m -> jcode = MNEW (u1, m->jcodelength);
984 suck_nbytes (m->jcode, m->jcodelength);
985 m -> exceptiontablelength = suck_u2 ();
986 m -> exceptiontable =
987 MNEW (exceptiontable, m->exceptiontablelength);
990 count_vmcode_len += m->jcodelength + 18;
991 count_extable_len += 8 * m->exceptiontablelength;
994 for (e=0; e < m->exceptiontablelength; e++) {
996 m -> exceptiontable[e].startpc = suck_u2();
997 m -> exceptiontable[e].endpc = suck_u2();
998 m -> exceptiontable[e].handlerpc = suck_u2();
1001 if (!idx) m -> exceptiontable[e].catchtype = NULL;
1003 m -> exceptiontable[e].catchtype =
1004 class_getconstant (c, idx, CONSTANT_Class);
1008 skipattributes ( suck_u2() );
1015 /********************* Function: method_free ***********************************
1017 frees all memory that was allocated for this method
1019 *******************************************************************************/
1021 static void method_free (methodinfo *m)
1023 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1024 if (m->exceptiontable)
1025 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1026 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1027 if (m->stubroutine) {
1028 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1029 else removecompilerstub (m->stubroutine);
1034 /************** Function: method_display (debugging only) **************/
1036 void method_display (methodinfo *m)
1039 printflags (m -> flags);
1041 utf_display (m -> name);
1043 utf_display (m -> descriptor);
1048 /******************** Function: method_canoverwrite ****************************
1050 Check if m and old are identical with respect to type and name. This means
1051 that old can be overwritten with m.
1053 *******************************************************************************/
1055 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1057 if (m->name != old->name) return false;
1058 if (m->descriptor != old->descriptor) return false;
1059 if (m->flags & ACC_STATIC) return false;
1066 /******************************************************************************/
1067 /************************ Functions for class *********************************/
1068 /******************************************************************************/
1071 /******************** function:: class_getconstant ******************************
1073 retrieves the value at position 'pos' of the constantpool of a class
1074 if the type of the value is other than 'ctype' the system is stopped
1076 *******************************************************************************/
1078 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1080 /* invalid position in constantpool */
1081 if (pos >= c->cpcount)
1082 panic ("Attempt to access constant outside range");
1084 /* check type of constantpool entry */
1086 if (c->cptags[pos] != ctype) {
1087 class_showconstantpool(c);
1088 error ("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1089 (int) ctype, (int) c->cptags[pos] );
1092 return c->cpinfos[pos];
1096 /********************* Function: class_constanttype ****************************
1098 Determines the type of a class entry in the ConstantPool
1100 *******************************************************************************/
1102 u4 class_constanttype (classinfo *c, u4 pos)
1104 if (pos >= c->cpcount)
1105 panic ("Attempt to access constant outside range");
1106 return c->cptags[pos];
1110 /******************** function: class_loadcpool ********************************
1112 loads the constantpool of a class,
1113 the entries are transformed into a simpler format
1114 by resolving references
1115 (a detailed overview of the compact structures can be found in global.h)
1117 *******************************************************************************/
1119 static void class_loadcpool (classinfo *c)
1122 /* The following structures are used to save information which cannot be
1123 processed during the first pass. After the complete constantpool has
1124 been traversed the references can be resolved.
1125 (only in specific order) */
1127 /* CONSTANT_Class_info entries */
1128 typedef struct forward_class {
1129 struct forward_class *next;
1134 /* CONSTANT_String */
1135 typedef struct forward_string {
1136 struct forward_string *next;
1141 /* CONSTANT_NameAndType */
1142 typedef struct forward_nameandtype {
1143 struct forward_nameandtype *next;
1147 } forward_nameandtype;
1149 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1150 typedef struct forward_fieldmethint {
1151 struct forward_fieldmethint *next;
1155 u2 nameandtype_index;
1156 } forward_fieldmethint;
1160 long int dumpsize = dump_size ();
1162 forward_class *forward_classes = NULL;
1163 forward_string *forward_strings = NULL;
1164 forward_nameandtype *forward_nameandtypes = NULL;
1165 forward_fieldmethint *forward_fieldmethints = NULL;
1167 /* number of entries in the constant_pool table */
1168 u4 cpcount = c -> cpcount = suck_u2();
1169 /* allocate memory */
1170 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1171 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1174 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1177 /* initialize constantpool */
1178 for (idx=0; idx<cpcount; idx++) {
1179 cptags[idx] = CONSTANT_UNUSED;
1180 cpinfos[idx] = NULL;
1184 /******* first pass *******/
1185 /* entries which cannot be resolved now are written into
1186 temporary structures and traversed again later */
1189 while (idx < cpcount) {
1190 /* get constant type */
1194 case CONSTANT_Class: {
1195 forward_class *nfc = DNEW(forward_class);
1197 nfc -> next = forward_classes;
1198 forward_classes = nfc;
1200 nfc -> thisindex = idx;
1201 /* reference to CONSTANT_NameAndType */
1202 nfc -> name_index = suck_u2 ();
1208 case CONSTANT_Fieldref:
1209 case CONSTANT_Methodref:
1210 case CONSTANT_InterfaceMethodref: {
1211 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1213 nff -> next = forward_fieldmethints;
1214 forward_fieldmethints = nff;
1216 nff -> thisindex = idx;
1219 /* class or interface type that contains the declaration of the field or method */
1220 nff -> class_index = suck_u2 ();
1221 /* name and descriptor of the field or method */
1222 nff -> nameandtype_index = suck_u2 ();
1228 case CONSTANT_String: {
1229 forward_string *nfs = DNEW (forward_string);
1231 nfs -> next = forward_strings;
1232 forward_strings = nfs;
1234 nfs -> thisindex = idx;
1235 /* reference to CONSTANT_Utf8_info with string characters */
1236 nfs -> string_index = suck_u2 ();
1242 case CONSTANT_NameAndType: {
1243 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1245 nfn -> next = forward_nameandtypes;
1246 forward_nameandtypes = nfn;
1248 nfn -> thisindex = idx;
1249 /* reference to CONSTANT_Utf8_info containing simple name */
1250 nfn -> name_index = suck_u2 ();
1251 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1252 nfn -> sig_index = suck_u2 ();
1258 case CONSTANT_Integer: {
1259 constant_integer *ci = NEW (constant_integer);
1262 count_const_pool_len += sizeof(constant_integer);
1265 ci -> value = suck_s4 ();
1266 cptags [idx] = CONSTANT_Integer;
1273 case CONSTANT_Float: {
1274 constant_float *cf = NEW (constant_float);
1277 count_const_pool_len += sizeof(constant_float);
1280 cf -> value = suck_float ();
1281 cptags [idx] = CONSTANT_Float;
1287 case CONSTANT_Long: {
1288 constant_long *cl = NEW(constant_long);
1291 count_const_pool_len += sizeof(constant_long);
1294 cl -> value = suck_s8 ();
1295 cptags [idx] = CONSTANT_Long;
1301 case CONSTANT_Double: {
1302 constant_double *cd = NEW(constant_double);
1305 count_const_pool_len += sizeof(constant_double);
1308 cd -> value = suck_double ();
1309 cptags [idx] = CONSTANT_Double;
1315 case CONSTANT_Utf8: {
1317 /* number of bytes in the bytes array (not string-length) */
1318 u4 length = suck_u2();
1319 cptags [idx] = CONSTANT_Utf8;
1320 /* validate the string */
1321 ASSERT_LEFT(length);
1322 if (!is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1323 panic("Invalid UTF-8 string");
1324 /* insert utf-string into the utf-symboltable */
1325 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1326 /* skip bytes of the string */
1327 skip_nbytes(length);
1333 error ("Unkown constant type: %d",(int) t);
1341 /* resolve entries in temporary structures */
1343 while (forward_classes) {
1345 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1347 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1348 /* retrieve class from class-table */
1349 cpinfos [forward_classes -> thisindex] = class_new (name);
1351 forward_classes = forward_classes -> next;
1355 while (forward_strings) {
1357 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1359 log_text("forward_string:");
1360 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1362 log_text("\n------------------"); */
1363 /* resolve utf-string */
1364 cptags [forward_strings -> thisindex] = CONSTANT_String;
1365 cpinfos [forward_strings -> thisindex] = text;
1367 forward_strings = forward_strings -> next;
1370 while (forward_nameandtypes) {
1371 constant_nameandtype *cn = NEW (constant_nameandtype);
1374 count_const_pool_len += sizeof(constant_nameandtype);
1377 /* resolve simple name and descriptor */
1378 cn -> name = class_getconstant
1379 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1380 cn -> descriptor = class_getconstant
1381 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1383 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1384 cpinfos [forward_nameandtypes -> thisindex] = cn;
1386 forward_nameandtypes = forward_nameandtypes -> next;
1390 while (forward_fieldmethints) {
1391 constant_nameandtype *nat;
1392 constant_FMIref *fmi = NEW (constant_FMIref);
1395 count_const_pool_len += sizeof(constant_FMIref);
1397 /* resolve simple name and descriptor */
1398 nat = class_getconstant
1399 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1402 log_text("trying to resolve:");
1403 log_text(nat->name->text);
1404 switch(forward_fieldmethints ->tag) {
1405 case CONSTANT_Fieldref:
1406 log_text("CONSTANT_Fieldref");
1408 case CONSTANT_InterfaceMethodref:
1409 log_text("CONSTANT_InterfaceMethodref");
1411 case CONSTANT_Methodref:
1412 log_text("CONSTANT_Methodref");
1416 fmi -> class = class_getconstant
1417 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1418 fmi -> name = nat -> name;
1419 fmi -> descriptor = nat -> descriptor;
1421 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1422 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1424 switch (forward_fieldmethints -> tag) {
1425 case CONSTANT_Fieldref: /* check validity of descriptor */
1426 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1428 case CONSTANT_InterfaceMethodref:
1429 case CONSTANT_Methodref: /* check validity of descriptor */
1430 /* XXX check special names (<init>) */
1431 checkmethoddescriptor (fmi->descriptor);
1435 forward_fieldmethints = forward_fieldmethints -> next;
1439 /* class_showconstantpool(c); */
1441 dump_release (dumpsize);
1445 /********************** Function: class_load ***********************************
1447 Loads everything interesting about a class from the class file. The
1448 'classinfo' structure must have been allocated previously.
1450 The super class and the interfaces implemented by this class need not be
1451 loaded. The link is set later by the function 'class_link'.
1453 The loaded class is removed from the list 'unloadedclasses' and added to
1454 the list 'unlinkedclasses'.
1456 *******************************************************************************/
1458 static int class_load(classinfo *c)
1464 count_class_loads++;
1467 /* output for debugging purposes */
1469 char logtext[MAXLOGTEXT];
1470 sprintf(logtext, "Loading class: ");
1471 utf_sprint(logtext+strlen(logtext), c->name);
1475 /* load classdata, throw exception on error */
1477 if (!suck_start(c->name)) {
1478 throw_classnotfoundexception2(c->name);
1482 /* check signature */
1483 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1487 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1488 error ("File version %d.%d is not supported",
1489 (int) ma, (int) mi);
1492 class_loadcpool (c);
1494 c->erroneous_state=0;
1495 c->initializing_thread=0;
1497 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1498 c -> impldBy = NULL;
1501 c -> flags = suck_u2 ();
1502 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1507 /* retrieve superclass */
1508 if ( (i = suck_u2 () ) ) {
1509 c -> super = class_getconstant (c, i, CONSTANT_Class);
1515 /* retrieve interfaces */
1516 c -> interfacescount = suck_u2 ();
1517 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1518 for (i=0; i < c -> interfacescount; i++) {
1519 c -> interfaces [i] =
1520 class_getconstant (c, suck_u2(), CONSTANT_Class);
1524 c -> fieldscount = suck_u2 ();
1525 /* utf_display(c->name);
1526 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1528 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1529 for (i=0; i < c -> fieldscount; i++) {
1530 field_load (&(c->fields[i]), c);
1534 c -> methodscount = suck_u2 ();
1535 c -> methods = MNEW (methodinfo, c -> methodscount);
1536 for (i=0; i < c -> methodscount; i++) {
1537 method_load (&(c -> methods [i]), c);
1541 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1542 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1543 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1546 /* load variable-length attribute structures */
1547 attribute_load (suck_u2(), c);
1552 /* remove class from list of unloaded classes and
1553 add to list of unlinked classes */
1554 list_remove (&unloadedclasses, c);
1555 list_addlast (&unlinkedclasses, c);
1562 /************** internal Function: class_highestinterface ***********************
1564 Used by the function class_link to determine the amount of memory needed
1565 for the interface table.
1567 *******************************************************************************/
1569 static s4 class_highestinterface (classinfo *c)
1574 if ( ! (c->flags & ACC_INTERFACE) ) {
1575 char logtext[MAXLOGTEXT];
1576 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1577 utf_sprint (logtext+strlen(logtext), c->name);
1582 for (i=0; i<c->interfacescount; i++) {
1583 s4 h2 = class_highestinterface (c->interfaces[i]);
1590 /* class_addinterface **********************************************************
1592 Is needed by class_link for adding a VTBL to a class. All interfaces
1593 implemented by ic are added as well.
1595 *******************************************************************************/
1597 static void class_addinterface (classinfo *c, classinfo *ic)
1601 vftbl *vftbl = c->vftbl;
1603 if (i >= vftbl->interfacetablelength)
1604 panic ("Inernal error: interfacetable overflow");
1605 if (vftbl->interfacetable[-i])
1608 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1609 vftbl->interfacevftbllength[i] = 1;
1610 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1611 vftbl->interfacetable[-i][0] = NULL;
1614 vftbl->interfacevftbllength[i] = ic->methodscount;
1615 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1618 count_vftbl_len += sizeof(methodptr) *
1619 (ic->methodscount + (ic->methodscount == 0));
1622 for (j=0; j<ic->methodscount; j++) {
1625 for (m = 0; m < sc->methodscount; m++) {
1626 methodinfo *mi = &(sc->methods[m]);
1627 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1628 vftbl->interfacetable[-i][j] =
1629 vftbl->table[mi->vftblindex];
1639 for (j = 0; j < ic->interfacescount; j++)
1640 class_addinterface(c, ic->interfaces[j]);
1644 /******************* Function: class_new_array *********************************
1646 This function is called by class_new to setup an array class.
1648 *******************************************************************************/
1651 class_new_array(classinfo *c)
1653 classinfo *comp = NULL;
1657 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1659 /* Array classes are not loaded from classfiles. */
1660 list_remove (&unloadedclasses, c);
1662 /* Check array class name */
1663 namelen = c->name->blength;
1664 if (namelen < 2 || c->name->text[0] != '[')
1665 panic("Invalid array class name");
1667 /* Check the component type */
1668 switch (c->name->text[1]) {
1670 /* c is an array of arrays. We have to create the component class. */
1671 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1675 /* c is an array of objects. */
1676 if (namelen < 4 || c->name->text[namelen-1] != ';')
1677 panic("Invalid array class name");
1678 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1682 /* Setup the array class */
1683 c->super = class_java_lang_Object;
1684 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1686 c->interfacescount = 2;
1687 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1688 c->interfaces[0] = class_java_lang_Cloneable;
1689 c->interfaces[1] = class_java_io_Serializable;
1691 c->methodscount = 1;
1692 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1695 memset(clone,0,sizeof(methodinfo));
1696 clone->flags = ACC_PUBLIC; /* XXX protected? */
1697 clone->name = utf_new_char("clone");
1698 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1700 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1701 clone->monoPoly = MONO; /* XXX should be poly? */
1703 /* XXX: field: length? */
1705 /* The array class has to be linked */
1706 list_addlast(&unlinkedclasses,c);
1709 * Array classes which are created after the other classes have been
1710 * loaded and linked are linked explicitely.
1715 loader_load(c->name); /* XXX handle errors */
1718 /****************** Function: class_link_array *********************************
1720 This function is called by class_link to create the
1721 arraydescriptor for an array class.
1723 This function returns NULL if the array cannot be linked because
1724 the component type has not been linked yet.
1726 *******************************************************************************/
1730 class_link_array(classinfo *c)
1732 classinfo *comp = NULL;
1733 int namelen = c->name->blength;
1734 arraydescriptor *desc;
1737 /* Check the component type */
1738 switch (c->name->text[1]) {
1740 /* c is an array of arrays. */
1741 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1742 if (!comp) panic("Could not find component array class.");
1746 /* c is an array of objects. */
1747 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1748 if (!comp) panic("Could not find component class.");
1752 /* If the component type has not been linked return NULL */
1753 if (comp && !comp->linked)
1756 /* Allocate the arraydescriptor */
1757 desc = NEW(arraydescriptor);
1760 /* c is an array of references */
1761 desc->arraytype = ARRAYTYPE_OBJECT;
1762 desc->componentsize = sizeof(void*);
1763 desc->dataoffset = OFFSET(java_objectarray,data);
1765 compvftbl = comp->vftbl;
1767 panic("Component class has no vftbl.");
1768 desc->componentvftbl = compvftbl;
1770 if (compvftbl->arraydesc) {
1771 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1772 desc->dimension = compvftbl->arraydesc->dimension + 1;
1773 desc->elementtype = compvftbl->arraydesc->elementtype;
1776 desc->elementvftbl = compvftbl;
1777 desc->dimension = 1;
1778 desc->elementtype = ARRAYTYPE_OBJECT;
1782 /* c is an array of a primitive type */
1783 switch (c->name->text[1]) {
1784 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1785 desc->dataoffset = OFFSET(java_booleanarray,data);
1786 desc->componentsize = sizeof(u1); break;
1787 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1788 desc->dataoffset = OFFSET(java_bytearray,data);
1789 desc->componentsize = sizeof(u1); break;
1790 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1791 desc->dataoffset = OFFSET(java_chararray,data);
1792 desc->componentsize = sizeof(u2); break;
1793 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1794 desc->dataoffset = OFFSET(java_doublearray,data);
1795 desc->componentsize = sizeof(double); break;
1796 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1797 desc->dataoffset = OFFSET(java_floatarray,data);
1798 desc->componentsize = sizeof(float); break;
1799 case 'I': desc->arraytype = ARRAYTYPE_INT;
1800 desc->dataoffset = OFFSET(java_intarray,data);
1801 desc->componentsize = sizeof(s4); break;
1802 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1803 desc->dataoffset = OFFSET(java_longarray,data);
1804 desc->componentsize = sizeof(s8); break;
1805 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1806 desc->dataoffset = OFFSET(java_shortarray,data);
1807 desc->componentsize = sizeof(s2); break;
1809 panic("Invalid array class name");
1812 desc->componentvftbl = NULL;
1813 desc->elementvftbl = NULL;
1814 desc->dimension = 1;
1815 desc->elementtype = desc->arraytype;
1821 /********************** Function: class_link ***********************************
1823 Tries to link a class. The super class and every implemented interface must
1824 already have been linked. The function calculates the length in bytes that
1825 an instance of this class requires as well as the VTBL for methods and
1828 If the class can be linked, it is removed from the list 'unlinkedclasses'
1829 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1832 Attention: If cyclical class definitions are encountered, the program gets
1833 into an infinite loop (we'll have to work that out)
1835 *******************************************************************************/
1837 void class_link(classinfo *c)
1839 s4 supervftbllength; /* vftbllegnth of super class */
1840 s4 vftbllength; /* vftbllength of current class */
1841 s4 interfacetablelength; /* interface table length */
1842 classinfo *super = c->super; /* super class */
1843 classinfo *ic, *c2; /* intermediate class variables */
1844 vftbl *v; /* vftbl of current class */
1845 s4 i; /* interface/method/field counter */
1846 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1849 /* check if all superclasses are already linked, if not put c at end of
1850 unlinked list and return. Additionally initialize class fields. */
1852 /* check interfaces */
1854 for (i = 0; i < c->interfacescount; i++) {
1855 ic = c->interfaces[i];
1857 list_remove(&unlinkedclasses, c);
1858 list_addlast(&unlinkedclasses, c);
1863 /* check super class */
1865 if (super == NULL) { /* class java.long.Object */
1867 c->classUsed = USED; /* Object class is always used CO-RT*/
1868 c -> impldBy = NULL;
1869 c->instancesize = sizeof(java_objectheader);
1871 vftbllength = supervftbllength = 0;
1873 c->finalizer = NULL;
1876 if (!super->linked) {
1877 list_remove(&unlinkedclasses, c);
1878 list_addlast(&unlinkedclasses, c);
1882 /* handle array classes */
1883 if (c->name->text[0] == '[')
1884 if ((arraydesc = class_link_array(c)) == NULL) {
1885 list_remove(&unlinkedclasses, c);
1886 list_addlast(&unlinkedclasses, c);
1890 if (c->flags & ACC_INTERFACE)
1891 c->index = interfaceindex++;
1893 c->index = super->index + 1;
1895 c->instancesize = super->instancesize;
1897 vftbllength = supervftbllength = super->vftbl->vftbllength;
1899 c->finalizer = super->finalizer;
1904 char logtext[MAXLOGTEXT];
1905 sprintf (logtext, "Linking Class: ");
1906 utf_sprint (logtext+strlen(logtext), c->name );
1910 /* compute vftbl length */
1912 for (i = 0; i < c->methodscount; i++) {
1913 methodinfo *m = &(c->methods[i]);
1915 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1916 classinfo *sc = super;
1919 for (j = 0; j < sc->methodscount; j++) {
1920 if (method_canoverwrite(m, &(sc->methods[j]))) {
1921 m->vftblindex = sc->methods[j].vftblindex;
1922 goto foundvftblindex;
1927 m->vftblindex = (vftbllength++);
1933 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1936 /* compute interfacetable length */
1938 interfacetablelength = 0;
1941 for (i = 0; i < c2->interfacescount; i++) {
1942 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1943 if (h > interfacetablelength)
1944 interfacetablelength = h;
1949 /* allocate virtual function table */
1951 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1952 (vftbllength - 1) + sizeof(methodptr*) *
1953 (interfacetablelength - (interfacetablelength > 0)));
1954 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1955 (interfacetablelength > 1));
1956 c->header.vftbl = c->vftbl = v;
1958 v->vftbllength = vftbllength;
1959 v->interfacetablelength = interfacetablelength;
1960 v->arraydesc = arraydesc;
1962 /* store interface index in vftbl */
1963 if (c->flags & ACC_INTERFACE)
1964 v->baseval = -(c->index);
1966 /* copy virtual function table of super class */
1968 for (i = 0; i < supervftbllength; i++)
1969 v->table[i] = super->vftbl->table[i];
1971 /* add method stubs into virtual function table */
1973 for (i = 0; i < c->methodscount; i++) {
1974 methodinfo *m = &(c->methods[i]);
1975 if (!(m->flags & ACC_STATIC)) {
1976 v->table[m->vftblindex] = m->stubroutine;
1980 /* compute instance size and offset of each field */
1982 for (i = 0; i < c->fieldscount; i++) {
1984 fieldinfo *f = &(c->fields[i]);
1986 if (!(f->flags & ACC_STATIC) ) {
1987 dsize = desc_typesize (f->descriptor);
1988 c->instancesize = ALIGN (c->instancesize, dsize);
1989 f->offset = c->instancesize;
1990 c->instancesize += dsize;
1994 /* initialize interfacetable and interfacevftbllength */
1996 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1999 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2002 for (i = 0; i < interfacetablelength; i++) {
2003 v->interfacevftbllength[i] = 0;
2004 v->interfacetable[-i] = NULL;
2007 /* add interfaces */
2009 for (c2 = c; c2 != NULL; c2 = c2->super)
2010 for (i = 0; i < c2->interfacescount; i++) {
2011 class_addinterface (c, c2->interfaces[i]);
2014 /* add finalizer method (not for java.lang.Object) */
2016 if (super != NULL) {
2018 static utf *finame = NULL;
2019 static utf *fidesc = NULL;
2022 finame = utf_finalize;
2024 fidesc = utf_fidesc;
2026 fi = class_findmethod (c, finame, fidesc);
2028 if (!(fi->flags & ACC_STATIC)) {
2038 list_remove (&unlinkedclasses, c);
2039 list_addlast (&linkedclasses, c);
2044 /******************* Function: class_freepool **********************************
2046 Frees all resources used by this classes Constant Pool.
2048 *******************************************************************************/
2050 static void class_freecpool (classinfo *c)
2056 for (idx=0; idx < c->cpcount; idx++) {
2057 tag = c->cptags[idx];
2058 info = c->cpinfos[idx];
2062 case CONSTANT_Fieldref:
2063 case CONSTANT_Methodref:
2064 case CONSTANT_InterfaceMethodref:
2065 FREE (info, constant_FMIref);
2067 case CONSTANT_Integer:
2068 FREE (info, constant_integer);
2070 case CONSTANT_Float:
2071 FREE (info, constant_float);
2074 FREE (info, constant_long);
2076 case CONSTANT_Double:
2077 FREE (info, constant_double);
2079 case CONSTANT_NameAndType:
2080 FREE (info, constant_nameandtype);
2086 MFREE (c -> cptags, u1, c -> cpcount);
2087 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2091 /*********************** Function: class_free **********************************
2093 Frees all resources used by the class.
2095 *******************************************************************************/
2097 static void class_free (classinfo *c)
2102 class_freecpool (c);
2104 MFREE (c->interfaces, classinfo*, c->interfacescount);
2106 for (i = 0; i < c->fieldscount; i++)
2107 field_free(&(c->fields[i]));
2109 for (i = 0; i < c->methodscount; i++)
2110 method_free(&(c->methods[i]));
2111 MFREE (c->methods, methodinfo, c->methodscount);
2113 if ((v = c->vftbl) != NULL) {
2115 mem_free(v->arraydesc,sizeof(arraydescriptor));
2117 for (i = 0; i < v->interfacetablelength; i++) {
2118 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2120 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2122 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2123 sizeof(methodptr*) * (v->interfacetablelength -
2124 (v->interfacetablelength > 0));
2125 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2126 (v->interfacetablelength > 1));
2130 if (c->innerclasscount)
2131 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2133 /* if (c->classvftbl)
2134 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2139 /************************* Function: class_findfield ***************************
2141 Searches a 'classinfo' structure for a field having the given name and
2144 *******************************************************************************/
2147 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2152 for (i = 0; i < c->fieldscount; i++) {
2153 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2154 return &(c->fields[i]);
2157 panic ("Can not find field given in CONSTANT_Fieldref");
2162 /************************* Function: class_findmethod **************************
2164 Searches a 'classinfo' structure for a method having the given name and
2165 type and returns the index in the class info structure.
2166 If type is NULL, it is ignored.
2168 *******************************************************************************/
2170 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2173 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2175 int buffer_len, pos;
2177 #ifdef JOWENN_DEBUG1
2180 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2182 buffer = MNEW(char, buffer_len);
2184 strcpy(buffer, "class_findmethod: method:");
2185 utf_sprint(buffer+strlen(buffer), name);
2186 strcpy(buffer+strlen(buffer), ", desc: ");
2187 utf_sprint(buffer+strlen(buffer), desc);
2188 strcpy(buffer+strlen(buffer), ", classname: ");
2189 utf_sprint(buffer+strlen(buffer), c->name);
2193 MFREE(buffer, char, buffer_len);
2195 for (i = 0; i < c->methodscount; i++) {
2196 #ifdef JOWENN_DEBUG2
2198 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2200 buffer = MNEW(char, buffer_len);
2202 strcpy(buffer, "class_findmethod: comparing to method:");
2203 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2204 strcpy(buffer+strlen(buffer), ", desc: ");
2205 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2209 MFREE(buffer, char, buffer_len);
2213 if ((c->methods[i].name == name) && ((desc == NULL) ||
2214 (c->methods[i].descriptor == desc)))
2217 #ifdef JOWENN_DEBUG2
2218 class_showconstantpool(c);
2219 log_text("class_findmethod: returning NULL");
2226 /************************* Function: class_findmethod **************************
2228 Searches a 'classinfo' structure for a method having the given name and
2230 If type is NULL, it is ignored.
2232 *******************************************************************************/
2234 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2238 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2240 int buffer_len, pos;
2242 #ifdef JOWENN_DEBUG1
2245 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2247 buffer = MNEW(char, buffer_len);
2249 strcpy(buffer, "class_findmethod: method:");
2250 utf_sprint(buffer+strlen(buffer), name);
2251 strcpy(buffer+strlen(buffer), ", desc: ");
2252 utf_sprint(buffer+strlen(buffer), desc);
2253 strcpy(buffer+strlen(buffer), ", classname: ");
2254 utf_sprint(buffer+strlen(buffer), c->name);
2258 MFREE(buffer, char, buffer_len);
2260 for (i = 0; i < c->methodscount; i++) {
2261 #ifdef JOWENN_DEBUG2
2263 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2265 buffer = MNEW(char, buffer_len);
2267 strcpy(buffer, "class_findmethod: comparing to method:");
2268 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2269 strcpy(buffer+strlen(buffer), ", desc: ");
2270 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2274 MFREE(buffer, char, buffer_len);
2278 if ((c->methods[i].name == name) && ((desc == NULL) ||
2279 (c->methods[i].descriptor == desc)))
2280 return &(c->methods[i]);
2282 #ifdef JOWENN_DEBUG2
2283 class_showconstantpool(c);
2284 log_text("class_findmethod: returning NULL");
2288 s4 idx=class_findmethodIndex(c,name,desc);
2289 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2290 if (idx==-1) return NULL;
2291 return &(c->methods[idx]);
2295 /*********************** Function: class_fetchmethod **************************
2297 like class_findmethod, but aborts with an error if the method is not found
2299 *******************************************************************************/
2301 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2304 mi = class_findmethod(c,name,desc);
2306 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2307 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2308 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2309 panic("Method not found");
2314 /************************* Function: class_findmethod_approx ******************
2316 like class_findmethod but ignores the return value when comparing the
2319 *******************************************************************************/
2321 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2325 for (i = 0; i < c->methodscount; i++)
2326 if (c->methods[i].name == name) {
2327 utf *meth_descr = c->methods[i].descriptor;
2331 return &(c->methods[i]);
2333 if (desc->blength <= meth_descr->blength) {
2334 /* current position in utf text */
2335 char *desc_utf_ptr = desc->text;
2336 char *meth_utf_ptr = meth_descr->text;
2337 /* points behind utf strings */
2338 char *desc_end = utf_end(desc);
2339 char *meth_end = utf_end(meth_descr);
2342 /* compare argument types */
2343 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2345 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2346 break; /* no match */
2349 return &(c->methods[i]); /* all parameter types equal */
2357 /***************** Function: class_resolvemethod_approx ***********************
2359 Searches a class and every super class for a method (without paying
2360 attention to the return value)
2362 *******************************************************************************/
2364 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2367 /* search for method (ignore returntype) */
2368 methodinfo *m = class_findmethod_approx (c, name, desc);
2371 /* search superclass */
2378 /************************* Function: class_resolvemethod ***********************
2380 Searches a class and every super class for a method.
2382 *******************************************************************************/
2384 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2387 methodinfo *m = class_findmethod(c, name, desc);
2389 /* search superclass */
2397 /************************* Function: class_issubclass **************************
2399 Checks if sub is a descendant of super.
2401 *******************************************************************************/
2403 bool class_issubclass(classinfo *sub, classinfo *super)
2406 if (!sub) return false;
2407 if (sub==super) return true;
2414 /****************** Initialization function for classes ******************
2416 In Java, every class can have a static initialization function. This
2417 function has to be called BEFORE calling other methods or accessing static
2420 *******************************************************************************/
2423 extern int blockInts;
2426 void class_init(classinfo *c)
2429 java_objectheader *exceptionptr;
2434 if (!makeinitializations)
2438 c -> initialized = true;
2443 count_class_inits++;
2447 class_init (c->super);
2448 for (i=0; i < c->interfacescount; i++)
2449 class_init(c->interfaces[i]); /* real */
2451 m = class_findmethod (c, utf_clinit, utf_fidesc);
2454 char logtext[MAXLOGTEXT];
2455 sprintf (logtext, "Class ");
2456 utf_sprint (logtext+strlen(logtext), c->name);
2457 sprintf (logtext+strlen(logtext), " has no initializer");
2460 /* goto callinitialize;*/
2464 if (! (m->flags & ACC_STATIC))
2465 panic ("Class initializer is not static!");
2468 char logtext[MAXLOGTEXT];
2469 sprintf (logtext, "Starting initializer for class: ");
2470 utf_sprint (logtext+strlen(logtext), c->name);
2479 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2482 assert(blockInts == 0);
2487 printf ("#### Initializer of ");
2488 utf_display (c->name);
2489 printf (" has thrown: ");
2490 utf_display (exceptionptr->vftbl->class->name);
2496 char logtext[MAXLOGTEXT];
2497 sprintf (logtext, "Finished initializer for class: ");
2498 utf_sprint (logtext+strlen(logtext), c->name);
2501 if (c->name == utf_systemclass) {
2502 /* class java.lang.System requires explicit initialization */
2505 printf ("#### Initializing class System");
2507 /* find initializing method */
2508 m = class_findmethod (c,
2509 utf_initsystemclass,
2513 /* no method found */
2514 /* printf("initializeSystemClass failed"); */
2522 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2525 assert(blockInts == 0);
2530 printf ("#### initializeSystemClass has thrown: ");
2531 utf_display (exceptionptr->vftbl->class->name);
2542 /********* Function: find_class_method_constant *********/
2543 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2548 for (i=0; i<c->cpcount; i++) {
2550 e = c -> cpinfos [i];
2553 switch (c -> cptags [i]) {
2554 case CONSTANT_Methodref:
2556 constant_FMIref *fmi = e;
2557 if ( (fmi->class->name == c1)
2558 && (fmi->name == m1)
2559 && (fmi->descriptor == d1)) {
2566 case CONSTANT_InterfaceMethodref:
2568 constant_FMIref *fmi = e;
2569 if ( (fmi->class->name == c1)
2570 && (fmi->name == m1)
2571 && (fmi->descriptor == d1)) {
2585 void class_showconstanti(classinfo *c, int ii)
2591 printf ("#%d: ", (int) i);
2593 switch (c->cptags [i]) {
2594 case CONSTANT_Class:
2595 printf("Classreference -> ");
2596 utf_display(((classinfo*)e)->name);
2599 case CONSTANT_Fieldref:
2600 printf("Fieldref -> "); goto displayFMIi;
2601 case CONSTANT_Methodref:
2602 printf("Methodref -> "); goto displayFMIi;
2603 case CONSTANT_InterfaceMethodref:
2604 printf("InterfaceMethod -> "); goto displayFMIi;
2607 constant_FMIref *fmi = e;
2608 utf_display(fmi->class->name);
2610 utf_display(fmi->name);
2612 utf_display(fmi->descriptor);
2616 case CONSTANT_String:
2617 printf("String -> ");
2620 case CONSTANT_Integer:
2621 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2623 case CONSTANT_Float:
2624 printf("Float -> %f", ((constant_float*)e)->value);
2626 case CONSTANT_Double:
2627 printf("Double -> %f", ((constant_double*)e)->value);
2631 u8 v = ((constant_long*)e)->value;
2633 printf("Long -> %ld", (long int) v);
2635 printf("Long -> HI: %ld, LO: %ld\n",
2636 (long int) v.high, (long int) v.low);
2640 case CONSTANT_NameAndType:
2642 constant_nameandtype *cnt = e;
2643 printf("NameAndType: ");
2644 utf_display(cnt->name);
2646 utf_display(cnt->descriptor);
2654 panic("Invalid type of ConstantPool-Entry");
2661 void class_showconstantpool (classinfo *c)
2666 printf ("---- dump of constant pool ----\n");
2668 for (i=0; i<c->cpcount; i++) {
2669 printf ("#%d: ", (int) i);
2671 e = c -> cpinfos [i];
2674 switch (c -> cptags [i]) {
2675 case CONSTANT_Class:
2676 printf ("Classreference -> ");
2677 utf_display ( ((classinfo*)e) -> name );
2680 case CONSTANT_Fieldref:
2681 printf ("Fieldref -> "); goto displayFMI;
2682 case CONSTANT_Methodref:
2683 printf ("Methodref -> "); goto displayFMI;
2684 case CONSTANT_InterfaceMethodref:
2685 printf ("InterfaceMethod -> "); goto displayFMI;
2688 constant_FMIref *fmi = e;
2689 utf_display ( fmi->class->name );
2691 utf_display ( fmi->name);
2693 utf_display ( fmi->descriptor );
2697 case CONSTANT_String:
2698 printf ("String -> ");
2701 case CONSTANT_Integer:
2702 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2704 case CONSTANT_Float:
2705 printf ("Float -> %f", ((constant_float*)e) -> value);
2707 case CONSTANT_Double:
2708 printf ("Double -> %f", ((constant_double*)e) -> value);
2712 u8 v = ((constant_long*)e) -> value;
2714 printf ("Long -> %ld", (long int) v);
2716 printf ("Long -> HI: %ld, LO: %ld\n",
2717 (long int) v.high, (long int) v.low);
2721 case CONSTANT_NameAndType:
2723 constant_nameandtype *cnt = e;
2724 printf ("NameAndType: ");
2725 utf_display (cnt->name);
2727 utf_display (cnt->descriptor);
2731 printf ("Utf8 -> ");
2735 panic ("Invalid type of ConstantPool-Entry");
2745 /********** Function: class_showmethods (debugging only) *************/
2747 void class_showmethods (classinfo *c)
2751 printf ("--------- Fields and Methods ----------------\n");
2752 printf ("Flags: "); printflags (c->flags); printf ("\n");
2754 printf ("This: "); utf_display (c->name); printf ("\n");
2756 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2758 printf ("Index: %d\n", c->index);
2760 printf ("interfaces:\n");
2761 for (i=0; i < c-> interfacescount; i++) {
2763 utf_display (c -> interfaces[i] -> name);
2764 printf (" (%d)\n", c->interfaces[i] -> index);
2767 printf ("fields:\n");
2768 for (i=0; i < c -> fieldscount; i++) {
2769 field_display (&(c -> fields[i]));
2772 printf ("methods:\n");
2773 for (i=0; i < c -> methodscount; i++) {
2774 methodinfo *m = &(c->methods[i]);
2775 if ( !(m->flags & ACC_STATIC))
2776 printf ("vftblindex: %d ", m->vftblindex);
2778 method_display ( m );
2782 printf ("Virtual function table:\n");
2783 for (i=0; i<c->vftbl->vftbllength; i++) {
2784 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2791 /******************************************************************************/
2792 /******************* General functions for the class loader *******************/
2793 /******************************************************************************/
2795 /********************* Function: loader_load ***********************************
2797 Loads and links the class desired class and each class and interface
2799 Returns: a pointer to this class
2801 *******************************************************************************/
2803 static int loader_load_running = 0;
2805 classinfo *loader_load (utf *topname)
2809 long int starttime=0,stoptime=0;
2810 classinfo *notlinkable;
2813 /* avoid recursive calls */
2814 if (loader_load_running)
2815 return class_new(topname);
2816 loader_load_running++;
2818 intsDisable(); /* schani */
2821 starttime = getcputime();
2823 top = class_new (topname);
2826 while ( (c = list_first(&unloadedclasses)) ) {
2827 if (!class_load (c)) {
2828 if (linkverbose) dolog("Failed to load class");
2829 list_remove (&unloadedclasses, c);
2835 if (linkverbose) dolog("Linking...");
2836 /* XXX added a hack to break infinite linking loops. A better
2837 * linking algorithm would be nice. -Edwin */
2839 while ( (c = list_first(&unlinkedclasses)) ) {
2844 else if (notlinkable == c) {
2845 /* We tried to link this class for the second time and
2846 * no other classes were linked in between, so we are
2849 if (linkverbose) dolog("Cannot resolve linking dependencies");
2852 throw_linkageerror2(c->name);
2859 if (linkverbose) dolog("Linking done.");
2862 loader_compute_subclasses();
2865 if (getloadingtime) {
2866 stoptime = getcputime();
2867 loadingtime += (stoptime-starttime);
2871 loader_load_running--;
2873 /* check if a former loader_load call tried to load/link the class and failed.
2874 This is needed because the class didn't appear in the undloadclasses or unlinkedclasses list during this class; */
2877 if (linkverbose) dolog("Failed to load class (former call)");
2878 throw_classnotfoundexception2(top->name);
2880 } else if (!top->linked) {
2881 if (linkverbose) dolog("Failed to link class (former call)");
2882 throw_linkageerror2(top->name);
2887 intsRestore(); /* schani */
2889 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
2894 /****************** Function: loader_load_sysclass ****************************
2896 Loads and links the class desired class and each class and interface
2899 The pointer to the classinfo is stored in *top if top != NULL.
2900 The pointer is also returned.
2902 If the class could not be loaded the function aborts with an error.
2904 *******************************************************************************/
2906 classinfo *loader_load_sysclass(classinfo **top,utf *topname)
2910 if ((cls = loader_load(topname)) == NULL) {
2911 log_plain("Could not important system class: ");
2912 log_plain_utf(topname);
2914 panic("Could not load important system class");
2917 if (top) *top = cls;
2922 /**************** function: create_primitive_classes ***************************
2924 create classes representing primitive types
2926 ********************************************************************************/
2929 void create_primitive_classes()
2933 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2934 /* create primitive class */
2935 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2936 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2937 c -> impldBy = NULL;
2939 /* prevent loader from loading primitive class */
2940 list_remove (&unloadedclasses, c);
2942 /* add to unlinked classes */
2943 list_addlast (&unlinkedclasses, c);
2944 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
2947 primitivetype_table[i].class_primitive = c;
2949 /* create class for wrapping the primitive type */
2950 primitivetype_table[i].class_wrap =
2951 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2952 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2953 primitivetype_table[i].class_wrap -> impldBy = NULL;
2955 /* create the primitive array class */
2956 if (primitivetype_table[i].arrayname) {
2957 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2958 primitivetype_table[i].arrayclass = c;
2960 if (!c->linked) class_link(c);
2961 primitivetype_table[i].arrayvftbl = c->vftbl;
2966 /**************** function: class_primitive_from_sig ***************************
2968 return the primitive class indicated by the given signature character
2970 If the descriptor does not indicate a valid primitive type the
2971 return value is NULL.
2973 ********************************************************************************/
2975 classinfo *class_primitive_from_sig(char sig)
2978 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2979 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2980 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2981 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2982 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2983 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2984 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2985 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2986 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2991 /****************** function: class_from_descriptor ****************************
2993 return the class indicated by the given descriptor
2995 utf_ptr....first character of descriptor
2996 end_ptr....first character after the end of the string
2997 next.......if non-NULL, *next is set to the first character after
2998 the descriptor. (Undefined if an error occurs.)
3000 mode.......a combination (binary or) of the following flags:
3002 (Flags marked with * are the default settings.)
3004 What to do if a reference type descriptor is parsed successfully:
3006 CLASSLOAD_SKIP...skip it and return something != NULL
3007 * CLASSLOAD_NEW....get classinfo * via class_new
3008 CLASSLOAD_LOAD...get classinfo * via loader_load
3010 How to handle primitive types:
3012 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3013 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3015 How to handle "V" descriptors:
3017 * CLASSLOAD_VOID.....handle it like other primitive types
3018 CLASSLOAD_NOVOID...treat it as an error
3020 How to deal with extra characters after the end of the
3023 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3024 CLASSLOAD_CHECKEND.....treat them as an error
3026 How to deal with errors:
3028 * CLASSLOAD_PANIC....abort execution with an error message
3029 CLASSLOAD_NOPANIC..return NULL on error
3031 ********************************************************************************/
3034 class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
3036 char *start = utf_ptr;
3040 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3042 if (mode & CLASSLOAD_CHECKEND)
3043 error |= (utf_ptr != end_ptr);
3046 if (next) *next = utf_ptr;
3050 if (mode & CLASSLOAD_NOVOID)
3061 return (mode & CLASSLOAD_NULLPRIMITIVE)
3063 : class_primitive_from_sig(*start);
3070 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3071 name = utf_new(start,utf_ptr-start);
3072 return (mode & CLASSLOAD_LOAD)
3073 ? loader_load(name) : class_new(name); /* XXX */
3077 /* An error occurred */
3078 if (mode & CLASSLOAD_NOPANIC)
3081 log_plain("Invalid descriptor at beginning of '");
3082 log_plain_utf(utf_new(start,end_ptr-start));
3086 panic("Invalid descriptor");
3089 /******************* function: type_from_descriptor ****************************
3091 return the basic type indicated by the given descriptor
3093 This function parses a descriptor and returns its basic type as
3094 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3096 cls...if non-NULL the referenced variable is set to the classinfo *
3097 returned by class_from_descriptor.
3099 For documentation of the arguments utf_ptr, end_ptr, next and mode
3100 see class_from_descriptor. The only difference is that
3101 type_from_descriptor always uses CLASSLOAD_PANIC.
3103 ********************************************************************************/
3106 type_from_descriptor(classinfo **cls,char *utf_ptr,char *end_ptr,char **next,int mode)
3109 if (!cls) cls = &mycls;
3110 *cls = class_from_descriptor(utf_ptr,end_ptr,next,mode & (~CLASSLOAD_NOPANIC));
3127 return TYPE_ADDRESS;
3130 /*************** function: create_pseudo_classes *******************************
3132 create pseudo classes used by the typechecker
3134 ********************************************************************************/
3137 create_pseudo_classes()
3139 /* pseudo class for Arraystubs (extends java.lang.Object) */
3141 pseudo_class_Arraystub = class_new( utf_new_char("$ARRAYSTUB$") );
3142 list_remove(&unloadedclasses,pseudo_class_Arraystub);
3144 pseudo_class_Arraystub->super = class_java_lang_Object;
3145 pseudo_class_Arraystub->interfacescount = 2;
3146 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
3147 pseudo_class_Arraystub->interfaces[0] =
3148 class_java_lang_Cloneable;
3149 pseudo_class_Arraystub->interfaces[1] =
3150 class_java_io_Serializable;
3152 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
3153 class_link(pseudo_class_Arraystub);
3155 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3157 /* pseudo class representing the null type */
3159 pseudo_class_Null = class_new( utf_new_char("$NULL$") );
3160 list_remove(&unloadedclasses,pseudo_class_Null);
3162 pseudo_class_Null->super = class_java_lang_Object;
3164 list_addlast(&unlinkedclasses,pseudo_class_Null);
3165 class_link(pseudo_class_Null);
3167 /* pseudo class representing new uninitialized objects */
3169 pseudo_class_New = class_new( utf_new_char("$NEW$") );
3170 list_remove(&unloadedclasses,pseudo_class_New);
3172 pseudo_class_New->super = class_java_lang_Object;
3174 list_addlast(&unlinkedclasses,pseudo_class_New);
3175 class_link(pseudo_class_New);
3178 /********************** Function: loader_init **********************************
3180 Initializes all lists and loads all classes required for the system or the
3183 *******************************************************************************/
3185 void loader_init (u1 * stackbottom)
3190 log_text("Entering loader_init");
3193 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
3194 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
3195 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
3197 /* create utf-symbols for pointer comparison of frequently used strings */
3198 utf_innerclasses = utf_new_char("InnerClasses");
3199 utf_constantvalue = utf_new_char("ConstantValue");
3200 utf_code = utf_new_char("Code");
3201 utf_finalize = utf_new_char("finalize");
3202 utf_fidesc = utf_new_char("()V");
3203 utf_clinit = utf_new_char("<clinit>");
3204 utf_initsystemclass = utf_new_char("initializeSystemClass");
3205 utf_systemclass = utf_new_char("java/lang/System");
3206 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
3207 utf_initialize =utf_new_char("initialize");
3208 utf_initializedesc =utf_new_char("(I)V");
3210 utf_vmclass =utf_new_char("java/lang/VMClass");
3212 /* create some important classes */
3213 /* These classes have to be created now because the classinfo
3214 * pointers are used in the loading code.
3216 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
3217 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
3218 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
3219 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
3221 log_text("loader_init: java/lang/Object");
3222 /* load the classes which were created above */
3223 loader_load_sysclass (NULL,class_java_lang_Object->name);
3225 loader_inited=1; /*JOWENN*/
3227 loader_load_sysclass(&class_java_lang_Throwable,
3228 utf_new_char("java/lang/Throwable") );
3230 log_text("loader_init: loader_load: java/lang/ClassCastException");
3231 loader_load_sysclass(&class_java_lang_ClassCastException,
3232 utf_new_char ("java/lang/ClassCastException") );
3233 loader_load_sysclass(&class_java_lang_NullPointerException,
3234 utf_new_char ("java/lang/NullPointerException") );
3235 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3236 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
3237 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3238 utf_new_char ("java/lang/NegativeArraySizeException") );
3239 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3240 utf_new_char ("java/lang/OutOfMemoryError") );
3241 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3242 utf_new_char ("java/lang/ArrayStoreException") );
3243 loader_load_sysclass(&class_java_lang_ArithmeticException,
3244 utf_new_char ("java/lang/ArithmeticException") );
3245 loader_load_sysclass(&class_java_lang_ThreadDeath,
3246 utf_new_char ("java/lang/ThreadDeath") );/* schani */
3248 /* create classes representing primitive types */
3249 create_primitive_classes();
3251 /* create classes used by the typechecker */
3252 create_pseudo_classes();
3254 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3255 stringtable_update();
3263 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3264 proto_java_lang_ClassCastException =
3265 builtin_new(class_java_lang_ClassCastException);
3266 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3268 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3270 proto_java_lang_NullPointerException =
3271 builtin_new(class_java_lang_NullPointerException);
3272 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3273 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3275 proto_java_lang_ArrayIndexOutOfBoundsException =
3276 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3277 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3279 proto_java_lang_NegativeArraySizeException =
3280 builtin_new(class_java_lang_NegativeArraySizeException);
3281 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3283 proto_java_lang_OutOfMemoryError =
3284 builtin_new(class_java_lang_OutOfMemoryError);
3285 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3287 proto_java_lang_ArithmeticException =
3288 builtin_new(class_java_lang_ArithmeticException);
3289 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3291 proto_java_lang_ArrayStoreException =
3292 builtin_new(class_java_lang_ArrayStoreException);
3293 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3295 proto_java_lang_ThreadDeath = /* schani */
3296 builtin_new(class_java_lang_ThreadDeath);
3297 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3306 /********************* Function: loader_initclasses ****************************
3308 Initializes all loaded but uninitialized classes
3310 *******************************************************************************/
3312 void loader_initclasses ()
3316 intsDisable(); /* schani */
3318 if (makeinitializations) {
3319 c = list_first (&linkedclasses);
3322 c = list_next (&linkedclasses, c);
3326 intsRestore(); /* schani */
3329 static s4 classvalue;
3331 static void loader_compute_class_values (classinfo *c)
3335 c->vftbl->baseval = ++classvalue;
3338 while (subs != NULL) {
3339 loader_compute_class_values(subs);
3340 subs = subs->nextsub;
3342 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3347 for (i = 0; i < c->index; i++)
3349 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3350 utf_display(c->name);
3358 void loader_compute_subclasses ()
3362 intsDisable(); /* schani */
3364 c = list_first (&linkedclasses);
3366 if (!(c->flags & ACC_INTERFACE)) {
3370 c = list_next (&linkedclasses, c);
3373 c = list_first (&linkedclasses);
3375 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3376 c->nextsub = c->super->sub;
3379 c = list_next (&linkedclasses, c);
3382 loader_compute_class_values(class_java_lang_Object);
3384 intsRestore(); /* schani */
3389 /******************** function classloader_buffer ******************************
3391 sets buffer for reading classdata
3393 *******************************************************************************/
3395 void classload_buffer(u1 *buf, int len)
3398 classbuffer_size = len;
3399 classbuf_pos = buf - 1;
3403 /******************** Function: loader_close ***********************************
3407 *******************************************************************************/
3409 void loader_close ()
3413 while ( (c=list_first(&unloadedclasses)) ) {
3414 list_remove (&unloadedclasses,c);
3417 while ( (c=list_first(&unlinkedclasses)) ) {
3418 list_remove (&unlinkedclasses,c);
3421 while ( (c=list_first(&linkedclasses)) ) {
3422 list_remove (&linkedclasses,c);
3429 * These are local overrides for various environment variables in Emacs.
3430 * Please do not remove this and leave it at the end of the file, where
3431 * Emacs will automagically detect them.
3432 * ---------------------------------------------------------------------
3435 * indent-tabs-mode: t