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
32 $Id: loader.c 682 2003-12-01 15:33:30Z jowenn $
47 #include "toolbox/memory.h"
48 #include "toolbox/loging.h"
49 #include "threads/thread.h"
60 /* global variables ***********************************************************/
62 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
63 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
64 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
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 bool loadverbose = false; /* switches for debug messages */
76 bool linkverbose = false;
77 bool initverbose = false;
79 bool makeinitializations = true;
81 bool getloadingtime = false; /* to measure the runtime */
82 long int loadingtime = 0;
84 static s4 interfaceindex; /* sequential numbering of interfaces */
86 list unloadedclasses; /* list of all referenced but not loaded classes */
87 list unlinkedclasses; /* list of all loaded but not linked classes */
88 list linkedclasses; /* list of all completely linked classes */
91 /* utf-symbols for pointer comparison of frequently used strings */
93 static utf *utf_innerclasses; /* InnerClasses */
94 static utf *utf_constantvalue; /* ConstantValue */
95 static utf *utf_code; /* Code */
96 static utf *utf_finalize; /* finalize */
97 static utf *utf_fidesc; /* ()V changed */
98 static utf *utf_clinit; /* <clinit> */
99 static utf *utf_initsystemclass; /* initializeSystemClass */
100 static utf *utf_systemclass; /* java/lang/System */
101 static utf *utf_vmclassloader; /*java/lang/VMClassLoader*/
102 static utf *utf_vmclass; /*java/lang/VMClassLoader*/
103 static utf *utf_initialize;
104 static utf *utf_initializedesc;
108 static unzFile uf = 0;
118 /* important system classes ***************************************************/
120 classinfo *class_java_lang_Object;
121 classinfo *class_java_lang_String;
123 classinfo *class_java_lang_Throwable;
124 classinfo *class_java_lang_Cloneable;
125 classinfo *class_java_io_Serializable;
127 /* Pseudo classes for the typechecker */
128 classinfo *pseudo_class_Arraystub = NULL;
129 classinfo *pseudo_class_Null = NULL;
130 vftbl *pseudo_class_Arraystub_vftbl = NULL;
133 /* These are made static so they cannot be used for throwing in native */
135 static classinfo *class_java_lang_ClassCastException;
136 static classinfo *class_java_lang_NullPointerException;
137 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
138 static classinfo *class_java_lang_NegativeArraySizeException;
139 static classinfo *class_java_lang_OutOfMemoryError;
140 static classinfo *class_java_lang_ArithmeticException;
141 static classinfo *class_java_lang_ArrayStoreException;
142 static classinfo *class_java_lang_ThreadDeath;
144 static methodinfo method_clone_array;
146 static int loader_inited = 0;
148 /******************************************************************************
150 structure for primitive classes: contains the class for wrapping the
151 primitive type, the primitive class, the name of the class for wrapping,
152 the one character type signature and the name of the primitive class
154 ******************************************************************************/
156 /* CAUTION: Don't change the order of the types. This table is indexed
157 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
159 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
160 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
161 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
162 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
163 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
164 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
165 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
166 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
167 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
168 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }};
170 /* instances of important system classes **************************************/
172 java_objectheader *proto_java_lang_ClassCastException;
173 java_objectheader *proto_java_lang_NullPointerException;
174 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
175 java_objectheader *proto_java_lang_NegativeArraySizeException;
176 java_objectheader *proto_java_lang_OutOfMemoryError;
177 java_objectheader *proto_java_lang_ArithmeticException;
178 java_objectheader *proto_java_lang_ArrayStoreException;
179 java_objectheader *proto_java_lang_ThreadDeath;
181 /************* functions for reading classdata *********************************
183 getting classdata in blocks of variable size
184 (8,16,32,64-bit integer or float)
186 *******************************************************************************/
188 static char *classpath = ""; /* searchpath for classfiles */
189 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
190 static u1 *classbuf_pos; /* current position in classfile buffer */
191 static int classbuffer_size; /* size of classfile-data */
193 /* transfer block of classfile data into a buffer */
195 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
198 /* skip block of classfile data */
200 #define skip_nbytes(len) classbuf_pos+=len;
204 return *++classbuf_pos;
208 u1 a=suck_u1(), b=suck_u1();
209 return ((u2)a<<8)+(u2)b;
213 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
214 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
216 #define suck_s8() (s8) suck_u8()
217 #define suck_s2() (s2) suck_u2()
218 #define suck_s4() (s4) suck_u4()
219 #define suck_s1() (s1) suck_u1()
222 /* get u8 from classfile data */
229 return (hi << 32) + lo;
239 /* get float from classfile data */
240 static float suck_float()
247 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
248 memcpy((u1*) (&f), buffer, 4);
250 suck_nbytes((u1*) (&f), 4);
253 PANICIF (sizeof(float) != 4, "Incompatible float-format");
259 /* get double from classfile data */
260 static double suck_double()
267 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
268 memcpy((u1*) (&d), buffer, 8);
270 suck_nbytes((u1*) (&d), 8);
273 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
279 /************************** function suck_init *********************************
281 called once at startup, sets the searchpath for the classfiles
283 *******************************************************************************/
285 void suck_init(char *cpath)
292 /************************** function suck_start ********************************
294 returns true if classbuffer is already loaded or a file for the
295 specified class has succussfully been read in. All directories of
296 the searchpath are used to find the classfile (<classname>.class).
297 Returns false if no classfile is found and writes an error message.
299 *******************************************************************************/
301 bool suck_start(utf *classname)
304 #define MAXFILENAME 1000 /* maximum length of a filename */
306 char filename[MAXFILENAME+10]; /* room for '.class' */
307 char *pathpos; /* position in searchpath */
308 char c, *utf_ptr; /* pointer to the next utf8-character */
310 int filenamelen, err;
314 if (classbuffer) /* classbuffer is already valid */
321 /* skip path separator */
323 while (*pathpos == ':')
326 /* extract directory from searchpath */
329 while ((*pathpos) && (*pathpos != ':')) {
330 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
331 filename[filenamelen++] = *(pathpos++);
335 if (filenamelen > 4) {
336 if ( ((filename[filenamelen - 1] == 'p') || (filename[filenamelen - 1] == 'P')) &
337 ((filename[filenamelen - 2] == 'i') || (filename[filenamelen - 2] == 'I')) &
338 ((filename[filenamelen - 3] == 'z') || (filename[filenamelen - 3] == 'Z')) ) {
345 filename[filenamelen++] = '\0';
346 if (uf == 0) uf = unzOpen(filename);
348 utf_ptr = classname->text;
350 while (utf_ptr < utf_end(classname)) {
351 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
353 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
355 filename[filenamelen++] = c;
357 strcpy(filename + filenamelen, ".class");
358 if (cacao_locate(uf,classname) == UNZ_OK) {
359 unz_file_info file_info;
360 log_text("Class found in zip file");
361 if (unzGetCurrentFileInfo(uf, &file_info, filename,
362 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
363 if (unzOpenCurrentFile(uf) == UNZ_OK) {
364 classbuffer_size = file_info.uncompressed_size;
365 classbuffer = MNEW(u1, classbuffer_size);
366 classbuf_pos = classbuffer - 1;
367 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
368 if (unzReadCurrentFile(uf, classbuffer, classbuffer_size) == classbuffer_size) {
369 unzCloseCurrentFile(uf);
372 MFREE(classbuffer, u1, classbuffer_size);
373 log_text("Error while unzipping");
375 } else log_text("Error while opening file in archive");
376 } else log_text("Error while retrieving fileinfo");
378 unzCloseCurrentFile(uf);
383 filename[filenamelen++] = '/';
385 /* add classname to filename */
387 utf_ptr = classname->text;
388 while (utf_ptr < utf_end(classname)) {
389 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
391 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
393 filename[filenamelen++] = c;
398 strcpy(filename + filenamelen, ".class");
400 classfile = fopen(filename, "r");
401 if (classfile) { /* file exists */
403 /* determine size of classfile */
405 err = stat(filename, &buffer);
407 if (!err) { /* read classfile data */
408 classbuffer_size = buffer.st_size;
409 classbuffer = MNEW(u1, classbuffer_size);
410 classbuf_pos = classbuffer - 1;
411 fread(classbuffer, 1, classbuffer_size, classfile);
419 sprintf(logtext, "Warning: Can not open class file '%s'", filename);
427 /************************** function suck_stop *********************************
429 frees memory for buffer with classfile data.
430 Caution: this function may only be called if buffer has been allocated
431 by suck_start with reading a file
433 *******************************************************************************/
437 /* determine amount of classdata not retrieved by suck-operations */
439 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
441 if (classdata_left > 0) {
443 sprintf(logtext, "There are %d access bytes at end of classfile",
450 MFREE(classbuffer, u1, classbuffer_size);
455 /******************************************************************************/
456 /******************* Some support functions ***********************************/
457 /******************************************************************************/
461 void fprintflags (FILE *fp, u2 f)
463 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
464 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
465 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
466 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
467 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
468 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
469 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
470 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
471 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
472 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
473 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
476 /********** internal function: printflags (only for debugging) ***************/
477 void printflags (u2 f)
479 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
480 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
481 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
482 if ( f & ACC_STATIC ) printf (" STATIC");
483 if ( f & ACC_FINAL ) printf (" FINAL");
484 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
485 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
486 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
487 if ( f & ACC_NATIVE ) printf (" NATIVE");
488 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
489 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
493 /************************* Function: skipattribute *****************************
495 skips a (1) 'attribute' structure in the class file
497 *******************************************************************************/
499 static void skipattribute ()
502 skip_nbytes(suck_u4());
505 /********************** Function: skipattributebody ****************************
507 skips an attribute after the 16 bit reference to attribute_name has already
510 *******************************************************************************/
512 static void skipattributebody ()
514 skip_nbytes(suck_u4());
517 /************************* Function: skipattributes ****************************
519 skips num attribute structures
521 *******************************************************************************/
523 static void skipattributes (u4 num)
526 for (i = 0; i < num; i++)
530 /******************** function: innerclass_getconstant ************************
532 like class_getconstant, but if cptags is ZERO null is returned
534 *******************************************************************************/
536 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
538 /* invalid position in constantpool */
539 if (pos >= c->cpcount)
540 panic ("Attempt to access constant outside range");
542 /* constantpool entry of type 0 */
546 /* check type of constantpool entry */
547 if (c->cptags[pos] != ctype) {
548 sprintf (logtext, "Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
549 (int) ctype, (int) c->cptags[pos] );
553 return c->cpinfos[pos];
556 /************************ function: attribute_load ****************************
558 read attributes from classfile
560 *******************************************************************************/
562 static void attribute_load (u4 num, classinfo *c)
566 for (i = 0; i < num; i++) {
567 /* retrieve attribute name */
568 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
570 if ( aname == utf_innerclasses) {
571 /* innerclasses attribute */
573 /* skip attribute length */
575 /* number of records */
576 c->innerclasscount = suck_u2();
577 /* allocate memory for innerclass structure */
578 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
580 for (j=0;j<c->innerclasscount;j++) {
582 /* The innerclass structure contains a class with an encoded name,
583 its defining scope, its simple name and a bitmask of the access flags.
584 If an inner class is not a member, its outer_class is NULL,
585 if a class is anonymous, its name is NULL. */
587 innerclassinfo *info = c->innerclass + j;
589 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
590 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
591 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
592 info->flags = suck_u2 (); /* access_flags bitmask */
595 /* unknown attribute */
596 skipattributebody ();
601 /******************* function: checkfielddescriptor ****************************
603 checks whether a field-descriptor is valid and aborts otherwise
604 all referenced classes are inserted into the list of unloaded classes
606 *******************************************************************************/
608 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
610 char *tstart; /* pointer to start of classname */
612 char *start = utf_ptr;
614 switch (*utf_ptr++) {
628 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
629 panic ("Ill formed descriptor");
633 panic ("Ill formed descriptor");
636 /* exceeding characters */
637 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
641 /******************* function checkmethoddescriptor ****************************
643 checks whether a method-descriptor is valid and aborts otherwise.
644 All referenced classes are inserted into the list of unloaded classes.
646 *******************************************************************************/
648 static void checkmethoddescriptor (utf *d)
650 char *utf_ptr = d->text; /* current position in utf text */
651 char *end_pos = utf_end(d); /* points behind utf string */
652 char *tstart; /* pointer to start of classname */
656 /* method descriptor must start with parenthesis */
657 /* XXX check length */
658 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
660 /* XXX check length */
661 /* check arguments */
662 while ((c = *utf_ptr++) != ')') {
679 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
680 panic ("Ill formed method descriptor");
684 panic ("Ill formed methodtype-descriptor");
688 /* check returntype */
690 /* returntype void */
691 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
694 /* treat as field-descriptor */
695 checkfielddescriptor (utf_ptr,end_pos);
698 /***************** Function: print_arraydescriptor ****************************
700 Debugging helper for displaying an arraydescriptor
702 *******************************************************************************/
705 print_arraydescriptor(FILE *file,arraydescriptor *desc)
708 fprintf(file,"<NULL>");
713 if (desc->componentvftbl) {
714 if (desc->componentvftbl->class)
715 utf_fprint(file,desc->componentvftbl->class->name);
717 fprintf(file,"<no classinfo>");
723 if (desc->elementvftbl) {
724 if (desc->elementvftbl->class)
725 utf_fprint(file,desc->elementvftbl->class->name);
727 fprintf(file,"<no classinfo>");
731 fprintf(file,",%d,%d,%d,%d}",desc->arraytype,desc->dimension,
732 desc->dataoffset,desc->componentsize);
735 /******************************************************************************/
736 /************************** Functions for fields ****************************/
737 /******************************************************************************/
740 /************************ Function: field_load *********************************
742 Load everything about a class field from the class file and fill a
743 'fieldinfo' structure. For static fields, space in the data segment is
746 *******************************************************************************/
748 static void field_load (fieldinfo *f, classinfo *c)
753 f -> flags = suck_u2 (); /* ACC flags */
754 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
755 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
756 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
757 f -> offset = 0; /* offset from start of object */
761 case TYPE_INT: f->value.i = 0; break;
762 case TYPE_FLOAT: f->value.f = 0.0; break;
763 case TYPE_DOUBLE: f->value.d = 0.0; break;
764 case TYPE_ADDRESS: f->value.a = NULL;
765 heap_addreference (&(f->value.a)); /* make global reference (GC) */
769 f->value.l = 0; break;
771 f->value.l.low = 0; f->value.l.high = 0; break;
775 /* read attributes */
777 for (i=0; i<attrnum; i++) {
781 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
783 if ( aname != utf_constantvalue ) {
784 /* unknown attribute */
785 skipattributebody ();
788 /* constant value attribute */
790 /* skip attribute length */
792 /* index of value in constantpool */
795 /* initialize field with value from constantpool */
798 constant_integer *ci =
799 class_getconstant(c, pindex, CONSTANT_Integer);
800 f->value.i = ci -> value;
806 class_getconstant(c, pindex, CONSTANT_Long);
808 f->value.l = cl -> value;
814 class_getconstant(c, pindex, CONSTANT_Float);
816 f->value.f = cf->value;
821 constant_double *cd =
822 class_getconstant(c, pindex, CONSTANT_Double);
824 f->value.d = cd->value;
829 utf *u = class_getconstant(c, pindex, CONSTANT_String);
830 /* create javastring from compressed utf8-string */
831 f->value.a = literalstring_new(u);
836 log_text ("Invalid Constant - Type");
845 /********************** function: field_free **********************************/
847 static void field_free (fieldinfo *f)
853 /**************** Function: field_display (debugging only) ********************/
855 void field_display (fieldinfo *f)
858 printflags (f -> flags);
860 utf_display (f -> name);
862 utf_display (f -> descriptor);
863 printf (" offset: %ld\n", (long int) (f -> offset) );
867 /******************************************************************************/
868 /************************* Functions for methods ******************************/
869 /******************************************************************************/
872 /*********************** Function: method_load *********************************
874 Loads a method from the class file and fills an existing 'methodinfo'
875 structure. For native methods, the function pointer field is set to the
876 real function pointer, for JavaVM methods a pointer to the compiler is used
879 *******************************************************************************/
881 static void method_load (methodinfo *m, classinfo *c)
891 m -> flags = suck_u2 ();
892 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
893 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
896 m -> exceptiontable = NULL;
897 m -> entrypoint = NULL;
899 m -> stubroutine = NULL;
900 m -> methodUsed = NOTUSED;
901 m -> monoPoly = MONO;
903 m -> subRedefsUsed = 0;
907 if (! (m->flags & ACC_NATIVE) ) {
908 m -> stubroutine = createcompilerstub (m);
912 functionptr f = native_findfunction
913 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
915 m -> stubroutine = createnativestub (f, m);
921 for (i=0; i<attrnum; i++) {
924 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
926 if ( aname != utf_code) {
927 skipattributebody ();
930 if (m -> jcode) panic ("Two code-attributes for one method!");
933 m -> maxstack = suck_u2();
934 m -> maxlocals = suck_u2();
935 m -> jcodelength = suck_u4();
936 m -> jcode = MNEW (u1, m->jcodelength);
937 suck_nbytes (m->jcode, m->jcodelength);
938 m -> exceptiontablelength = suck_u2 ();
939 m -> exceptiontable =
940 MNEW (exceptiontable, m->exceptiontablelength);
943 count_vmcode_len += m->jcodelength + 18;
944 count_extable_len += 8 * m->exceptiontablelength;
947 for (e=0; e < m->exceptiontablelength; e++) {
949 m -> exceptiontable[e].startpc = suck_u2();
950 m -> exceptiontable[e].endpc = suck_u2();
951 m -> exceptiontable[e].handlerpc = suck_u2();
954 if (!idx) m -> exceptiontable[e].catchtype = NULL;
956 m -> exceptiontable[e].catchtype =
957 class_getconstant (c, idx, CONSTANT_Class);
961 skipattributes ( suck_u2() );
968 /********************* Function: method_free ***********************************
970 frees all memory that was allocated for this method
972 *******************************************************************************/
974 static void method_free (methodinfo *m)
976 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
977 if (m->exceptiontable)
978 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
979 if (m->mcode) CFREE (m->mcode, m->mcodelength);
980 if (m->stubroutine) {
981 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
982 else removecompilerstub (m->stubroutine);
987 /************** Function: method_display (debugging only) **************/
989 void method_display (methodinfo *m)
992 printflags (m -> flags);
994 utf_display (m -> name);
996 utf_display (m -> descriptor);
1001 /******************** Function: method_canoverwrite ****************************
1003 Check if m and old are identical with respect to type and name. This means
1004 that old can be overwritten with m.
1006 *******************************************************************************/
1008 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1010 if (m->name != old->name) return false;
1011 if (m->descriptor != old->descriptor) return false;
1012 if (m->flags & ACC_STATIC) return false;
1019 /******************************************************************************/
1020 /************************ Functions for class *********************************/
1021 /******************************************************************************/
1024 /******************** function:: class_getconstant ******************************
1026 retrieves the value at position 'pos' of the constantpool of a class
1027 if the type of the value is other than 'ctype' the system is stopped
1029 *******************************************************************************/
1031 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1033 /* invalid position in constantpool */
1034 if (pos >= c->cpcount)
1035 panic ("Attempt to access constant outside range");
1037 /* check type of constantpool entry */
1039 if (c->cptags[pos] != ctype) {
1040 class_showconstantpool(c);
1041 sprintf (logtext, "Type mismatch on constant: %d requested, %d here (class_getconstant)",
1042 (int) ctype, (int) c->cptags[pos] );
1046 return c->cpinfos[pos];
1050 /********************* Function: class_constanttype ****************************
1052 Determines the type of a class entry in the ConstantPool
1054 *******************************************************************************/
1056 u4 class_constanttype (classinfo *c, u4 pos)
1058 if (pos >= c->cpcount)
1059 panic ("Attempt to access constant outside range");
1060 return c->cptags[pos];
1064 /******************** function: class_loadcpool ********************************
1066 loads the constantpool of a class,
1067 the entries are transformed into a simpler format
1068 by resolving references
1069 (a detailed overview of the compact structures can be found in global.h)
1071 *******************************************************************************/
1073 static void class_loadcpool (classinfo *c)
1076 /* The following structures are used to save information which cannot be
1077 processed during the first pass. After the complete constantpool has
1078 been traversed the references can be resolved.
1079 (only in specific order) */
1081 /* CONSTANT_Class_info entries */
1082 typedef struct forward_class {
1083 struct forward_class *next;
1088 /* CONSTANT_String */
1089 typedef struct forward_string {
1090 struct forward_string *next;
1095 /* CONSTANT_NameAndType */
1096 typedef struct forward_nameandtype {
1097 struct forward_nameandtype *next;
1101 } forward_nameandtype;
1103 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1104 typedef struct forward_fieldmethint {
1105 struct forward_fieldmethint *next;
1109 u2 nameandtype_index;
1110 } forward_fieldmethint;
1114 long int dumpsize = dump_size ();
1116 forward_class *forward_classes = NULL;
1117 forward_string *forward_strings = NULL;
1118 forward_nameandtype *forward_nameandtypes = NULL;
1119 forward_fieldmethint *forward_fieldmethints = NULL;
1121 /* number of entries in the constant_pool table */
1122 u4 cpcount = c -> cpcount = suck_u2();
1123 /* allocate memory */
1124 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1125 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1128 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1131 /* initialize constantpool */
1132 for (idx=0; idx<cpcount; idx++) {
1133 cptags[idx] = CONSTANT_UNUSED;
1134 cpinfos[idx] = NULL;
1138 /******* first pass *******/
1139 /* entries which cannot be resolved now are written into
1140 temporary structures and traversed again later */
1143 while (idx < cpcount) {
1144 /* get constant type */
1148 case CONSTANT_Class: {
1149 forward_class *nfc = DNEW(forward_class);
1151 nfc -> next = forward_classes;
1152 forward_classes = nfc;
1154 nfc -> thisindex = idx;
1155 /* reference to CONSTANT_NameAndType */
1156 nfc -> name_index = suck_u2 ();
1162 case CONSTANT_Fieldref:
1163 case CONSTANT_Methodref:
1164 case CONSTANT_InterfaceMethodref: {
1165 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1167 nff -> next = forward_fieldmethints;
1168 forward_fieldmethints = nff;
1170 nff -> thisindex = idx;
1173 /* class or interface type that contains the declaration of the field or method */
1174 nff -> class_index = suck_u2 ();
1175 /* name and descriptor of the field or method */
1176 nff -> nameandtype_index = suck_u2 ();
1182 case CONSTANT_String: {
1183 forward_string *nfs = DNEW (forward_string);
1185 nfs -> next = forward_strings;
1186 forward_strings = nfs;
1188 nfs -> thisindex = idx;
1189 /* reference to CONSTANT_Utf8_info with string characters */
1190 nfs -> string_index = suck_u2 ();
1196 case CONSTANT_NameAndType: {
1197 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1199 nfn -> next = forward_nameandtypes;
1200 forward_nameandtypes = nfn;
1202 nfn -> thisindex = idx;
1203 /* reference to CONSTANT_Utf8_info containing simple name */
1204 nfn -> name_index = suck_u2 ();
1205 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1206 nfn -> sig_index = suck_u2 ();
1212 case CONSTANT_Integer: {
1213 constant_integer *ci = NEW (constant_integer);
1216 count_const_pool_len += sizeof(constant_integer);
1219 ci -> value = suck_s4 ();
1220 cptags [idx] = CONSTANT_Integer;
1227 case CONSTANT_Float: {
1228 constant_float *cf = NEW (constant_float);
1231 count_const_pool_len += sizeof(constant_float);
1234 cf -> value = suck_float ();
1235 cptags [idx] = CONSTANT_Float;
1241 case CONSTANT_Long: {
1242 constant_long *cl = NEW(constant_long);
1245 count_const_pool_len += sizeof(constant_long);
1248 cl -> value = suck_s8 ();
1249 cptags [idx] = CONSTANT_Long;
1255 case CONSTANT_Double: {
1256 constant_double *cd = NEW(constant_double);
1259 count_const_pool_len += sizeof(constant_double);
1262 cd -> value = suck_double ();
1263 cptags [idx] = CONSTANT_Double;
1269 case CONSTANT_Utf8: {
1271 /* number of bytes in the bytes array (not string-length) */
1272 u4 length = suck_u2();
1273 cptags [idx] = CONSTANT_Utf8;
1274 /* insert utf-string into the utf-symboltable */
1275 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1276 /* skip bytes of the string */
1277 skip_nbytes(length);
1283 sprintf (logtext, "Unkown constant type: %d",(int) t);
1292 /* resolve entries in temporary structures */
1294 while (forward_classes) {
1296 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1298 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1299 /* retrieve class from class-table */
1300 cpinfos [forward_classes -> thisindex] = class_new (name);
1302 forward_classes = forward_classes -> next;
1306 while (forward_strings) {
1308 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1310 log_text("forward_string:");
1311 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1313 log_text("\n------------------"); */
1314 /* resolve utf-string */
1315 cptags [forward_strings -> thisindex] = CONSTANT_String;
1316 cpinfos [forward_strings -> thisindex] = text;
1318 forward_strings = forward_strings -> next;
1321 while (forward_nameandtypes) {
1322 constant_nameandtype *cn = NEW (constant_nameandtype);
1325 count_const_pool_len += sizeof(constant_nameandtype);
1328 /* resolve simple name and descriptor */
1329 cn -> name = class_getconstant
1330 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1331 cn -> descriptor = class_getconstant
1332 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1334 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1335 cpinfos [forward_nameandtypes -> thisindex] = cn;
1337 forward_nameandtypes = forward_nameandtypes -> next;
1341 while (forward_fieldmethints) {
1342 constant_nameandtype *nat;
1343 constant_FMIref *fmi = NEW (constant_FMIref);
1346 count_const_pool_len += sizeof(constant_FMIref);
1348 /* resolve simple name and descriptor */
1349 nat = class_getconstant
1350 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1353 log_text("trying to resolve:");
1354 log_text(nat->name->text);
1355 switch(forward_fieldmethints ->tag) {
1356 case CONSTANT_Fieldref:
1357 log_text("CONSTANT_Fieldref");
1359 case CONSTANT_InterfaceMethodref:
1360 log_text("CONSTANT_InterfaceMethodref");
1362 case CONSTANT_Methodref:
1363 log_text("CONSTANT_Methodref");
1367 fmi -> class = class_getconstant
1368 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1369 fmi -> name = nat -> name;
1370 fmi -> descriptor = nat -> descriptor;
1372 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1373 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1375 switch (forward_fieldmethints -> tag) {
1376 case CONSTANT_Fieldref: /* check validity of descriptor */
1377 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1379 case CONSTANT_InterfaceMethodref:
1380 case CONSTANT_Methodref: /* check validity of descriptor */
1381 checkmethoddescriptor (fmi->descriptor);
1385 forward_fieldmethints = forward_fieldmethints -> next;
1389 /* class_showconstantpool(c); */
1391 dump_release (dumpsize);
1395 /********************** Function: class_load ***********************************
1397 Loads everything interesting about a class from the class file. The
1398 'classinfo' structure must have been allocated previously.
1400 The super class and the interfaces implemented by this class need not be
1401 loaded. The link is set later by the function 'class_link'.
1403 The loaded class is removed from the list 'unloadedclasses' and added to
1404 the list 'unlinkedclasses'.
1406 *******************************************************************************/
1408 static int class_load(classinfo *c)
1414 count_class_loads++;
1417 /* output for debugging purposes */
1419 sprintf(logtext, "Loading class: ");
1420 utf_sprint(logtext+strlen(logtext), c->name);
1424 /* load classdata, throw exception on error */
1426 if (!suck_start(c->name)) {
1427 throw_classnotfoundexception2(c->name);
1431 /* check signature */
1432 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1436 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1437 sprintf (logtext, "File version %d.%d is not supported",
1438 (int) ma, (int) mi);
1442 class_loadcpool (c);
1444 c->erroneous_state=0;
1445 c->initializing_thread=0;
1447 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1448 c -> impldBy = NULL;
1451 c -> flags = suck_u2 ();
1455 /* retrieve superclass */
1456 if ( (i = suck_u2 () ) ) {
1457 c -> super = class_getconstant (c, i, CONSTANT_Class);
1463 /* retrieve interfaces */
1464 c -> interfacescount = suck_u2 ();
1465 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1466 for (i=0; i < c -> interfacescount; i++) {
1467 c -> interfaces [i] =
1468 class_getconstant (c, suck_u2(), CONSTANT_Class);
1472 c -> fieldscount = suck_u2 ();
1473 /* utf_display(c->name);
1474 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1476 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1477 for (i=0; i < c -> fieldscount; i++) {
1478 field_load (&(c->fields[i]), c);
1482 c -> methodscount = suck_u2 ();
1483 c -> methods = MNEW (methodinfo, c -> methodscount);
1484 for (i=0; i < c -> methodscount; i++) {
1485 method_load (&(c -> methods [i]), c);
1489 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1490 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1491 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1494 /* load variable-length attribute structures */
1495 attribute_load (suck_u2(), c);
1500 /* remove class from list of unloaded classes and
1501 add to list of unlinked classes */
1502 list_remove (&unloadedclasses, c);
1503 list_addlast (&unlinkedclasses, c);
1510 /************** internal Function: class_highestinterface ***********************
1512 Used by the function class_link to determine the amount of memory needed
1513 for the interface table.
1515 *******************************************************************************/
1517 static s4 class_highestinterface (classinfo *c)
1522 if ( ! (c->flags & ACC_INTERFACE) ) {
1523 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1524 utf_sprint (logtext+strlen(logtext), c->name);
1529 for (i=0; i<c->interfacescount; i++) {
1530 s4 h2 = class_highestinterface (c->interfaces[i]);
1537 /* class_addinterface **********************************************************
1539 Is needed by class_link for adding a VTBL to a class. All interfaces
1540 implemented by ic are added as well.
1542 *******************************************************************************/
1544 static void class_addinterface (classinfo *c, classinfo *ic)
1548 vftbl *vftbl = c->vftbl;
1550 if (i >= vftbl->interfacetablelength)
1551 panic ("Inernal error: interfacetable overflow");
1552 if (vftbl->interfacetable[-i])
1555 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1556 vftbl->interfacevftbllength[i] = 1;
1557 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1558 vftbl->interfacetable[-i][0] = NULL;
1561 vftbl->interfacevftbllength[i] = ic->methodscount;
1562 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1565 count_vftbl_len += sizeof(methodptr) *
1566 (ic->methodscount + (ic->methodscount == 0));
1569 for (j=0; j<ic->methodscount; j++) {
1572 for (m = 0; m < sc->methodscount; m++) {
1573 methodinfo *mi = &(sc->methods[m]);
1574 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1575 vftbl->interfacetable[-i][j] =
1576 vftbl->table[mi->vftblindex];
1586 for (j = 0; j < ic->interfacescount; j++)
1587 class_addinterface(c, ic->interfaces[j]);
1591 /******************* Function: class_new_array *********************************
1593 This function is called by class_new to setup an array class.
1595 *******************************************************************************/
1598 class_new_array(classinfo *c)
1600 classinfo *comp = NULL;
1604 /* Array classes are not loaded from classfiles. */
1605 list_remove (&unloadedclasses, c);
1607 /* Check array class name */
1608 namelen = c->name->blength;
1609 if (namelen < 2 || c->name->text[0] != '[')
1610 panic("Invalid array class name.");
1612 /* Check the component type */
1613 switch (c->name->text[1]) {
1615 /* c is an array of arrays. We have to create the component class. */
1616 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1620 /* c is an array of objects. */
1621 if (namelen < 4 || c->name->text[namelen-1] != ';')
1622 panic("Invalid array class name.");
1623 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1627 /* Setup the array class */
1628 c->super = class_java_lang_Object;
1630 c->interfacescount = 2;
1631 c->interfaces = MNEW(classinfo*,2);
1632 c->interfaces[0] = class_java_lang_Cloneable;
1633 c->interfaces[1] = class_java_io_Serializable;
1635 c->methodscount = 1;
1636 c->methods = MNEW (methodinfo, c->methodscount);
1639 memset(clone,0,sizeof(methodinfo));
1640 clone->flags = ACC_PUBLIC; /* XXX protected? */
1641 clone->name = utf_new_char("clone");
1642 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1644 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1645 clone->monoPoly = MONO; /* XXX should be poly? */
1647 /* XXX: field: length? */
1649 /* The array class has to be linked */
1650 list_addlast(&unlinkedclasses,c);
1653 * Array classes which are created after the other classes have been
1654 * loaded and linked are linked explicitely.
1659 loader_load(c->name);
1662 /****************** Function: class_link_array *********************************
1664 This function is called by class_link to create the
1665 arraydescriptor for an array class.
1667 This function returns NULL if the array cannot be linked because
1668 the component type has not been linked yet.
1670 *******************************************************************************/
1674 class_link_array(classinfo *c)
1676 classinfo *comp = NULL;
1677 int namelen = c->name->blength;
1678 arraydescriptor *desc;
1681 /* Check the component type */
1682 switch (c->name->text[1]) {
1684 /* c is an array of arrays. */
1685 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1686 if (!comp) panic("Could not find component array class.");
1690 /* c is an array of objects. */
1691 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1692 if (!comp) panic("Could not find component class.");
1696 /* If the component type has not been linked return NULL */
1697 if (comp && !comp->linked)
1700 /* Allocate the arraydescriptor */
1701 desc = NEW(arraydescriptor);
1704 /* c is an array of references */
1705 desc->arraytype = ARRAYTYPE_OBJECT;
1706 desc->componentsize = sizeof(void*);
1707 desc->dataoffset = OFFSET(java_objectarray,data);
1709 compvftbl = comp->vftbl;
1711 panic("Component class has no vftbl.");
1712 desc->componentvftbl = compvftbl;
1714 if (compvftbl->arraydesc) {
1715 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1716 desc->dimension = compvftbl->arraydesc->dimension + 1;
1719 desc->elementvftbl = compvftbl;
1720 desc->dimension = 1;
1724 /* c is an array of a primitive type */
1725 switch (c->name->text[1]) {
1726 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1727 desc->dataoffset = OFFSET(java_booleanarray,data);
1728 desc->componentsize = sizeof(u1); break;
1729 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1730 desc->dataoffset = OFFSET(java_bytearray,data);
1731 desc->componentsize = sizeof(u1); break;
1732 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1733 desc->dataoffset = OFFSET(java_chararray,data);
1734 desc->componentsize = sizeof(u2); break;
1735 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1736 desc->dataoffset = OFFSET(java_doublearray,data);
1737 desc->componentsize = sizeof(double); break;
1738 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1739 desc->dataoffset = OFFSET(java_floatarray,data);
1740 desc->componentsize = sizeof(float); break;
1741 case 'I': desc->arraytype = ARRAYTYPE_INT;
1742 desc->dataoffset = OFFSET(java_intarray,data);
1743 desc->componentsize = sizeof(s4); break;
1744 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1745 desc->dataoffset = OFFSET(java_longarray,data);
1746 desc->componentsize = sizeof(s8); break;
1747 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1748 desc->dataoffset = OFFSET(java_shortarray,data);
1749 desc->componentsize = sizeof(s2); break;
1751 panic("Invalid array class name");
1754 desc->componentvftbl = NULL;
1755 desc->elementvftbl = NULL;
1756 desc->dimension = 1;
1762 /********************** Function: class_link ***********************************
1764 Tries to link a class. The super class and every implemented interface must
1765 already have been linked. The function calculates the length in bytes that
1766 an instance of this class requires as well as the VTBL for methods and
1769 If the class can be linked, it is removed from the list 'unlinkedclasses'
1770 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1773 Attention: If cyclical class definitions are encountered, the program gets
1774 into an infinite loop (we'll have to work that out)
1776 *******************************************************************************/
1778 void class_link(classinfo *c)
1780 s4 supervftbllength; /* vftbllegnth of super class */
1781 s4 vftbllength; /* vftbllength of current class */
1782 s4 interfacetablelength; /* interface table length */
1783 classinfo *super = c->super; /* super class */
1784 classinfo *ic, *c2; /* intermediate class variables */
1785 vftbl *v; /* vftbl of current class */
1786 s4 i; /* interface/method/field counter */
1787 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1790 /* check if all superclasses are already linked, if not put c at end of
1791 unlinked list and return. Additionally initialize class fields. */
1793 /* check interfaces */
1795 for (i = 0; i < c->interfacescount; i++) {
1796 ic = c->interfaces[i];
1798 list_remove(&unlinkedclasses, c);
1799 list_addlast(&unlinkedclasses, c);
1804 /* check super class */
1806 if (super == NULL) { /* class java.long.Object */
1808 c->classUsed = USED; /* Object class is always used CO-RT*/
1809 c -> impldBy = NULL;
1810 c->instancesize = sizeof(java_objectheader);
1812 vftbllength = supervftbllength = 0;
1814 c->finalizer = NULL;
1817 if (!super->linked) {
1818 list_remove(&unlinkedclasses, c);
1819 list_addlast(&unlinkedclasses, c);
1823 /* handle array classes */
1824 if (c->name->text[0] == '[')
1825 if ((arraydesc = class_link_array(c)) == NULL) {
1826 list_remove(&unlinkedclasses, c);
1827 list_addlast(&unlinkedclasses, c);
1831 if (c->flags & ACC_INTERFACE)
1832 c->index = interfaceindex++;
1834 c->index = super->index + 1;
1836 c->instancesize = super->instancesize;
1838 vftbllength = supervftbllength = super->vftbl->vftbllength;
1840 c->finalizer = super->finalizer;
1845 sprintf (logtext, "Linking Class: ");
1846 utf_sprint (logtext+strlen(logtext), c->name );
1850 /* compute vftbl length */
1852 for (i = 0; i < c->methodscount; i++) {
1853 methodinfo *m = &(c->methods[i]);
1855 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1856 classinfo *sc = super;
1859 for (j = 0; j < sc->methodscount; j++) {
1860 if (method_canoverwrite(m, &(sc->methods[j]))) {
1861 m->vftblindex = sc->methods[j].vftblindex;
1862 goto foundvftblindex;
1867 m->vftblindex = (vftbllength++);
1873 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1876 /* compute interfacetable length */
1878 interfacetablelength = 0;
1881 for (i = 0; i < c2->interfacescount; i++) {
1882 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1883 if (h > interfacetablelength)
1884 interfacetablelength = h;
1889 /* allocate virtual function table */
1891 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1892 (vftbllength - 1) + sizeof(methodptr*) *
1893 (interfacetablelength - (interfacetablelength > 0)));
1894 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1895 (interfacetablelength > 1));
1896 c->header.vftbl = c->vftbl = v;
1898 v->vftbllength = vftbllength;
1899 v->interfacetablelength = interfacetablelength;
1900 v->arraydesc = arraydesc;
1902 /* store interface index in vftbl */
1903 if (c->flags & ACC_INTERFACE)
1904 v->baseval = -(c->index);
1906 /* copy virtual function table of super class */
1908 for (i = 0; i < supervftbllength; i++)
1909 v->table[i] = super->vftbl->table[i];
1911 /* add method stubs into virtual function table */
1913 for (i = 0; i < c->methodscount; i++) {
1914 methodinfo *m = &(c->methods[i]);
1915 if (!(m->flags & ACC_STATIC)) {
1916 v->table[m->vftblindex] = m->stubroutine;
1920 /* compute instance size and offset of each field */
1922 for (i = 0; i < c->fieldscount; i++) {
1924 fieldinfo *f = &(c->fields[i]);
1926 if (!(f->flags & ACC_STATIC) ) {
1927 dsize = desc_typesize (f->descriptor);
1928 c->instancesize = ALIGN (c->instancesize, dsize);
1929 f->offset = c->instancesize;
1930 c->instancesize += dsize;
1934 /* initialize interfacetable and interfacevftbllength */
1936 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1939 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1942 for (i = 0; i < interfacetablelength; i++) {
1943 v->interfacevftbllength[i] = 0;
1944 v->interfacetable[-i] = NULL;
1947 /* add interfaces */
1949 for (c2 = c; c2 != NULL; c2 = c2->super)
1950 for (i = 0; i < c2->interfacescount; i++) {
1951 class_addinterface (c, c2->interfaces[i]);
1954 /* add finalizer method (not for java.lang.Object) */
1956 if (super != NULL) {
1958 static utf *finame = NULL;
1959 static utf *fidesc = NULL;
1962 finame = utf_finalize;
1964 fidesc = utf_fidesc;
1966 fi = class_findmethod (c, finame, fidesc);
1968 if (!(fi->flags & ACC_STATIC)) {
1978 list_remove (&unlinkedclasses, c);
1979 list_addlast (&linkedclasses, c);
1984 /******************* Function: class_freepool **********************************
1986 Frees all resources used by this classes Constant Pool.
1988 *******************************************************************************/
1990 static void class_freecpool (classinfo *c)
1996 for (idx=0; idx < c->cpcount; idx++) {
1997 tag = c->cptags[idx];
1998 info = c->cpinfos[idx];
2002 case CONSTANT_Fieldref:
2003 case CONSTANT_Methodref:
2004 case CONSTANT_InterfaceMethodref:
2005 FREE (info, constant_FMIref);
2007 case CONSTANT_Integer:
2008 FREE (info, constant_integer);
2010 case CONSTANT_Float:
2011 FREE (info, constant_float);
2014 FREE (info, constant_long);
2016 case CONSTANT_Double:
2017 FREE (info, constant_double);
2019 case CONSTANT_NameAndType:
2020 FREE (info, constant_nameandtype);
2026 MFREE (c -> cptags, u1, c -> cpcount);
2027 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2031 /*********************** Function: class_free **********************************
2033 Frees all resources used by the class.
2035 *******************************************************************************/
2037 static void class_free (classinfo *c)
2042 class_freecpool (c);
2044 MFREE (c->interfaces, classinfo*, c->interfacescount);
2046 for (i = 0; i < c->fieldscount; i++)
2047 field_free(&(c->fields[i]));
2049 for (i = 0; i < c->methodscount; i++)
2050 method_free(&(c->methods[i]));
2051 MFREE (c->methods, methodinfo, c->methodscount);
2053 if ((v = c->vftbl) != NULL) {
2055 mem_free(v->arraydesc,sizeof(arraydescriptor));
2057 for (i = 0; i < v->interfacetablelength; i++) {
2058 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2060 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2062 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2063 sizeof(methodptr*) * (v->interfacetablelength -
2064 (v->interfacetablelength > 0));
2065 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2066 (v->interfacetablelength > 1));
2070 if (c->innerclasscount)
2071 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2073 /* if (c->classvftbl)
2074 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2076 FREE (c, classinfo);
2079 /************************* Function: class_findfield ***************************
2081 Searches a 'classinfo' structure for a field having the given name and
2084 *******************************************************************************/
2087 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2092 for (i = 0; i < c->fieldscount; i++) {
2093 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2094 return &(c->fields[i]);
2097 panic ("Can not find field given in CONSTANT_Fieldref");
2102 /************************* Function: class_findmethod **************************
2104 Searches a 'classinfo' structure for a method having the given name and
2105 type and returns the index in the class info structure.
2106 If type is NULL, it is ignored.
2108 *******************************************************************************/
2110 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2113 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2115 int buffer_len, pos;
2117 #ifdef JOWENN_DEBUG1
2120 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2122 buffer = MNEW(char, buffer_len);
2124 strcpy(buffer, "class_findmethod: method:");
2125 utf_sprint(buffer+strlen(buffer), name);
2126 strcpy(buffer+strlen(buffer), ", desc: ");
2127 utf_sprint(buffer+strlen(buffer), desc);
2128 strcpy(buffer+strlen(buffer), ", classname: ");
2129 utf_sprint(buffer+strlen(buffer), c->name);
2133 MFREE(buffer, char, buffer_len);
2135 for (i = 0; i < c->methodscount; i++) {
2136 #ifdef JOWENN_DEBUG2
2138 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2140 buffer = MNEW(char, buffer_len);
2142 strcpy(buffer, "class_findmethod: comparing to method:");
2143 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2144 strcpy(buffer+strlen(buffer), ", desc: ");
2145 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2149 MFREE(buffer, char, buffer_len);
2153 if ((c->methods[i].name == name) && ((desc == NULL) ||
2154 (c->methods[i].descriptor == desc)))
2157 #ifdef JOWENN_DEBUG2
2158 class_showconstantpool(c);
2159 log_text("class_findmethod: returning NULL");
2166 /************************* Function: class_findmethod **************************
2168 Searches a 'classinfo' structure for a method having the given name and
2170 If type is NULL, it is ignored.
2172 *******************************************************************************/
2174 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2178 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2180 int buffer_len, pos;
2182 #ifdef JOWENN_DEBUG1
2185 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2187 buffer = MNEW(char, buffer_len);
2189 strcpy(buffer, "class_findmethod: method:");
2190 utf_sprint(buffer+strlen(buffer), name);
2191 strcpy(buffer+strlen(buffer), ", desc: ");
2192 utf_sprint(buffer+strlen(buffer), desc);
2193 strcpy(buffer+strlen(buffer), ", classname: ");
2194 utf_sprint(buffer+strlen(buffer), c->name);
2198 MFREE(buffer, char, buffer_len);
2200 for (i = 0; i < c->methodscount; i++) {
2201 #ifdef JOWENN_DEBUG2
2203 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2205 buffer = MNEW(char, buffer_len);
2207 strcpy(buffer, "class_findmethod: comparing to method:");
2208 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2209 strcpy(buffer+strlen(buffer), ", desc: ");
2210 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2214 MFREE(buffer, char, buffer_len);
2218 if ((c->methods[i].name == name) && ((desc == NULL) ||
2219 (c->methods[i].descriptor == desc)))
2220 return &(c->methods[i]);
2222 #ifdef JOWENN_DEBUG2
2223 class_showconstantpool(c);
2224 log_text("class_findmethod: returning NULL");
2228 s4 idx=class_findmethodIndex(c,name,desc);
2229 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2230 if (idx==-1) return NULL;
2231 return &(c->methods[idx]);
2239 /************************* Function: class_findmethod_approx ******************
2241 like class_findmethod but ignores the return value when comparing the
2244 *******************************************************************************/
2246 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2250 for (i = 0; i < c->methodscount; i++)
2251 if (c->methods[i].name == name) {
2252 utf *meth_descr = c->methods[i].descriptor;
2256 return &(c->methods[i]);
2258 if (desc->blength <= meth_descr->blength) {
2259 /* current position in utf text */
2260 char *desc_utf_ptr = desc->text;
2261 char *meth_utf_ptr = meth_descr->text;
2262 /* points behind utf strings */
2263 char *desc_end = utf_end(desc);
2264 char *meth_end = utf_end(meth_descr);
2267 /* compare argument types */
2268 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2270 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2271 break; /* no match */
2274 return &(c->methods[i]); /* all parameter types equal */
2282 /***************** Function: class_resolvemethod_approx ***********************
2284 Searches a class and every super class for a method (without paying
2285 attention to the return value)
2287 *******************************************************************************/
2289 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2292 /* search for method (ignore returntype) */
2293 methodinfo *m = class_findmethod_approx (c, name, desc);
2296 /* search superclass */
2303 /************************* Function: class_resolvemethod ***********************
2305 Searches a class and every super class for a method.
2307 *******************************************************************************/
2309 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2312 methodinfo *m = class_findmethod(c, name, desc);
2314 /* search superclass */
2322 /************************* Function: class_issubclass **************************
2324 Checks if sub is a descendant of super.
2326 *******************************************************************************/
2328 bool class_issubclass(classinfo *sub, classinfo *super)
2331 if (!sub) return false;
2332 if (sub==super) return true;
2339 /****************** Initialization function for classes ******************
2341 In Java, every class can have a static initialization function. This
2342 function has to be called BEFORE calling other methods or accessing static
2345 *******************************************************************************/
2348 extern int blockInts;
2351 void class_init(classinfo *c)
2354 java_objectheader *exceptionptr;
2359 if (!makeinitializations)
2363 c -> initialized = true;
2368 count_class_inits++;
2372 class_init (c->super);
2373 for (i=0; i < c->interfacescount; i++)
2374 class_init(c->interfaces[i]); /* real */
2376 m = class_findmethod (c, utf_clinit, utf_fidesc);
2379 sprintf (logtext, "Class ");
2380 utf_sprint (logtext+strlen(logtext), c->name);
2381 sprintf (logtext+strlen(logtext), " has no initializer");
2384 /* goto callinitialize;*/
2388 if (! (m->flags & ACC_STATIC))
2389 panic ("Class initializer is not static!");
2392 sprintf (logtext, "Starting initializer for class: ");
2393 utf_sprint (logtext+strlen(logtext), c->name);
2402 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2405 assert(blockInts == 0);
2410 printf ("#### Initializer of ");
2411 utf_display (c->name);
2412 printf (" has thrown: ");
2413 utf_display (exceptionptr->vftbl->class->name);
2419 sprintf (logtext, "Finished initializer for class: ");
2420 utf_sprint (logtext+strlen(logtext), c->name);
2423 if (c->name == utf_systemclass) {
2424 /* class java.lang.System requires explicit initialization */
2427 printf ("#### Initializing class System");
2429 /* find initializing method */
2430 m = class_findmethod (c,
2431 utf_initsystemclass,
2435 /* no method found */
2436 /* printf("initializeSystemClass failed"); */
2444 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2447 assert(blockInts == 0);
2452 printf ("#### initializeSystemClass has thrown: ");
2453 utf_display (exceptionptr->vftbl->class->name);
2464 /********* Function: find_class_method_constant *********/
2465 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2470 for (i=0; i<c->cpcount; i++) {
2472 e = c -> cpinfos [i];
2475 switch (c -> cptags [i]) {
2476 case CONSTANT_Methodref:
2478 constant_FMIref *fmi = e;
2479 if ( (fmi->class->name == c1)
2480 && (fmi->name == m1)
2481 && (fmi->descriptor == d1)) {
2488 case CONSTANT_InterfaceMethodref:
2490 constant_FMIref *fmi = e;
2491 if ( (fmi->class->name == c1)
2492 && (fmi->name == m1)
2493 && (fmi->descriptor == d1)) {
2507 void class_showconstanti(classinfo *c, int ii)
2513 printf ("#%d: ", (int) i);
2515 switch (c->cptags [i]) {
2516 case CONSTANT_Class:
2517 printf("Classreference -> ");
2518 utf_display(((classinfo*)e)->name);
2521 case CONSTANT_Fieldref:
2522 printf("Fieldref -> "); goto displayFMIi;
2523 case CONSTANT_Methodref:
2524 printf("Methodref -> "); goto displayFMIi;
2525 case CONSTANT_InterfaceMethodref:
2526 printf("InterfaceMethod -> "); goto displayFMIi;
2529 constant_FMIref *fmi = e;
2530 utf_display(fmi->class->name);
2532 utf_display(fmi->name);
2534 utf_display(fmi->descriptor);
2538 case CONSTANT_String:
2539 printf("String -> ");
2542 case CONSTANT_Integer:
2543 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2545 case CONSTANT_Float:
2546 printf("Float -> %f", ((constant_float*)e)->value);
2548 case CONSTANT_Double:
2549 printf("Double -> %f", ((constant_double*)e)->value);
2553 u8 v = ((constant_long*)e)->value;
2555 printf("Long -> %ld", (long int) v);
2557 printf("Long -> HI: %ld, LO: %ld\n",
2558 (long int) v.high, (long int) v.low);
2562 case CONSTANT_NameAndType:
2564 constant_nameandtype *cnt = e;
2565 printf("NameAndType: ");
2566 utf_display(cnt->name);
2568 utf_display(cnt->descriptor);
2576 panic("Invalid type of ConstantPool-Entry");
2583 void class_showconstantpool (classinfo *c)
2588 printf ("---- dump of constant pool ----\n");
2590 for (i=0; i<c->cpcount; i++) {
2591 printf ("#%d: ", (int) i);
2593 e = c -> cpinfos [i];
2596 switch (c -> cptags [i]) {
2597 case CONSTANT_Class:
2598 printf ("Classreference -> ");
2599 utf_display ( ((classinfo*)e) -> name );
2602 case CONSTANT_Fieldref:
2603 printf ("Fieldref -> "); goto displayFMI;
2604 case CONSTANT_Methodref:
2605 printf ("Methodref -> "); goto displayFMI;
2606 case CONSTANT_InterfaceMethodref:
2607 printf ("InterfaceMethod -> "); goto displayFMI;
2610 constant_FMIref *fmi = e;
2611 utf_display ( fmi->class->name );
2613 utf_display ( fmi->name);
2615 utf_display ( fmi->descriptor );
2619 case CONSTANT_String:
2620 printf ("String -> ");
2623 case CONSTANT_Integer:
2624 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2626 case CONSTANT_Float:
2627 printf ("Float -> %f", ((constant_float*)e) -> value);
2629 case CONSTANT_Double:
2630 printf ("Double -> %f", ((constant_double*)e) -> value);
2634 u8 v = ((constant_long*)e) -> value;
2636 printf ("Long -> %ld", (long int) v);
2638 printf ("Long -> HI: %ld, LO: %ld\n",
2639 (long int) v.high, (long int) v.low);
2643 case CONSTANT_NameAndType:
2645 constant_nameandtype *cnt = e;
2646 printf ("NameAndType: ");
2647 utf_display (cnt->name);
2649 utf_display (cnt->descriptor);
2653 printf ("Utf8 -> ");
2657 panic ("Invalid type of ConstantPool-Entry");
2667 /********** Function: class_showmethods (debugging only) *************/
2669 void class_showmethods (classinfo *c)
2673 printf ("--------- Fields and Methods ----------------\n");
2674 printf ("Flags: "); printflags (c->flags); printf ("\n");
2676 printf ("This: "); utf_display (c->name); printf ("\n");
2678 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2680 printf ("Index: %d\n", c->index);
2682 printf ("interfaces:\n");
2683 for (i=0; i < c-> interfacescount; i++) {
2685 utf_display (c -> interfaces[i] -> name);
2686 printf (" (%d)\n", c->interfaces[i] -> index);
2689 printf ("fields:\n");
2690 for (i=0; i < c -> fieldscount; i++) {
2691 field_display (&(c -> fields[i]));
2694 printf ("methods:\n");
2695 for (i=0; i < c -> methodscount; i++) {
2696 methodinfo *m = &(c->methods[i]);
2697 if ( !(m->flags & ACC_STATIC))
2698 printf ("vftblindex: %d ", m->vftblindex);
2700 method_display ( m );
2704 printf ("Virtual function table:\n");
2705 for (i=0; i<c->vftbl->vftbllength; i++) {
2706 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2713 /******************************************************************************/
2714 /******************* General functions for the class loader *******************/
2715 /******************************************************************************/
2717 /********************* Function: loader_load ***********************************
2719 Loads and links the class desired class and each class and interface
2721 Returns: a pointer to this class
2723 *******************************************************************************/
2725 static int loader_load_running = 0;
2727 classinfo *loader_load (utf *topname)
2731 long int starttime=0,stoptime=0;
2733 /* avoid recursive calls */
2734 if (loader_load_running)
2735 return class_new(topname);
2736 loader_load_running++;
2738 intsDisable(); /* schani */
2741 starttime = getcputime();
2743 top = class_new (topname);
2746 while ( (c = list_first(&unloadedclasses)) ) {
2747 if (!class_load (c)) {
2748 list_remove (&unloadedclasses, c);
2754 while ( (c = list_first(&unlinkedclasses)) ) {
2759 loader_compute_subclasses();
2762 if (getloadingtime) {
2763 stoptime = getcputime();
2764 loadingtime += (stoptime-starttime);
2768 loader_load_running--;
2770 /* check if a former loader_load call tried to load/link the class and failed.
2771 This is needed because the class didn't appear in the undloadclasses or unlinkedclasses list during this class; */
2774 throw_classnotfoundexception2(top->name);
2776 } else if (!top->linked) {
2777 throw_linkageerror2(top->name);
2782 intsRestore(); /* schani */
2788 /**************** function: create_primitive_classes ***************************
2790 create classes representing primitive types
2792 ********************************************************************************/
2795 void create_primitive_classes()
2799 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2800 /* create primitive class */
2801 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2802 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2803 c -> impldBy = NULL;
2805 /* prevent loader from loading primitive class */
2806 list_remove (&unloadedclasses, c);
2808 /* add to unlinked classes */
2809 list_addlast (&unlinkedclasses, c);
2810 c -> super = class_java_lang_Object;
2813 primitivetype_table[i].class_primitive = c;
2815 /* create class for wrapping the primitive type */
2816 primitivetype_table[i].class_wrap =
2817 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2818 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2819 primitivetype_table[i].class_wrap -> impldBy = NULL;
2821 /* create the primitive array class */
2822 if (primitivetype_table[i].arrayname) {
2823 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2824 primitivetype_table[i].arrayclass = c;
2826 if (!c->linked) class_link(c);
2827 primitivetype_table[i].arrayvftbl = c->vftbl;
2832 /**************** function: class_primitive_from_sig ***************************
2834 return the primitive class indicated by the given signature character
2836 If the descriptor does not indicate a valid primitive type the
2837 return value is NULL.
2839 ********************************************************************************/
2841 classinfo *class_primitive_from_sig(char sig)
2844 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2845 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2846 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2847 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2848 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2849 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2850 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2851 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2852 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2857 /****************** function: class_from_descriptor ****************************
2859 return the class indicated by the given descriptor
2861 utf_ptr....first character of descriptor
2862 end_ptr....first character after the end of the string
2863 next.......if non-NULL, *next is set to the first character after
2865 mode.......what to do if a class descriptor is parsed successfully:
2866 CLASSLOAD_SKIP...skip it and return something != NULL
2867 CLASSLOAD_NEW....get classinfo * via class_new
2868 CLASSLOAD_LOAD...get classinfo * via loader_load
2870 If the descriptor is invalid the return value is NULL
2872 ********************************************************************************/
2874 classinfo *class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
2876 char *start = utf_ptr;
2880 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
2881 if (error) return NULL;
2882 if (next) *next = utf_ptr;
2890 if (mode == CLASSLOAD_SKIP) return class_java_lang_Object;
2891 name = utf_new(start,utf_ptr-start);
2892 return (mode == CLASSLOAD_LOAD) ? loader_load(name) : class_new(name);
2894 return class_primitive_from_sig(*start);
2898 /*************** function: create_pseudo_classes *******************************
2900 create pseudo classes used by the typechecker
2902 ********************************************************************************/
2905 create_pseudo_classes()
2907 /* pseudo class for Arraystubs (extends java.lang.Object) */
2909 pseudo_class_Arraystub = class_new( utf_new_char(";Arraystub;") );
2910 list_remove(&unloadedclasses,pseudo_class_Arraystub);
2912 pseudo_class_Arraystub->super = class_java_lang_Object;
2913 pseudo_class_Arraystub->interfacescount = 2;
2914 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
2915 pseudo_class_Arraystub->interfaces[0] =
2916 class_java_lang_Cloneable;
2917 pseudo_class_Arraystub->interfaces[1] =
2918 class_java_io_Serializable;
2920 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
2921 class_link(pseudo_class_Arraystub);
2923 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
2925 /* pseudo class representing the null type */
2927 pseudo_class_Null = class_new( utf_new_char(";Null;") );
2928 list_remove(&unloadedclasses,pseudo_class_Null);
2930 pseudo_class_Null->super = class_java_lang_Object;
2932 list_addlast(&unlinkedclasses,pseudo_class_Null);
2933 class_link(pseudo_class_Null);
2936 /********************** Function: loader_init **********************************
2938 Initializes all lists and loads all classes required for the system or the
2941 *******************************************************************************/
2943 void loader_init (u1 * stackbottom)
2948 log_text("Entering loader_init");
2951 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2952 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2953 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2955 /* create utf-symbols for pointer comparison of frequently used strings */
2956 utf_innerclasses = utf_new_char("InnerClasses");
2957 utf_constantvalue = utf_new_char("ConstantValue");
2958 utf_code = utf_new_char("Code");
2959 utf_finalize = utf_new_char("finalize");
2960 utf_fidesc = utf_new_char("()V");
2961 utf_clinit = utf_new_char("<clinit>");
2962 utf_initsystemclass = utf_new_char("initializeSystemClass");
2963 utf_systemclass = utf_new_char("java/lang/System");
2964 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
2965 utf_initialize =utf_new_char("initialize");
2966 utf_initializedesc =utf_new_char("(I)V");
2968 utf_vmclass =utf_new_char("java/lang/VMClass");
2970 /* create some important classes */
2971 /* These classes have to be created now because the classinfo
2972 * pointers are used in the loading code.
2974 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
2975 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
2976 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
2977 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
2979 log_text("loader_init: java/lang/Object");
2980 /* load the classes which were created above */
2981 loader_load (class_java_lang_Object->name);
2983 loader_inited=1; /*JOWENN*/
2985 class_java_lang_Throwable =
2986 loader_load( utf_new_char("java/lang/Throwable") );
2988 log_text("loader_init: loader_load: java/lang/ClassCastException");
2989 class_java_lang_ClassCastException =
2990 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2991 class_java_lang_NullPointerException =
2992 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2993 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2994 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2995 class_java_lang_NegativeArraySizeException = loader_load (
2996 utf_new_char ("java/lang/NegativeArraySizeException") );
2997 class_java_lang_OutOfMemoryError = loader_load (
2998 utf_new_char ("java/lang/OutOfMemoryError") );
2999 class_java_lang_ArrayStoreException =
3000 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
3001 class_java_lang_ArithmeticException =
3002 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
3003 class_java_lang_ThreadDeath = /* schani */
3004 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
3005 /* create classes representing primitive types */
3006 create_primitive_classes();
3008 /* create classes used by the typechecker */
3009 create_pseudo_classes();
3011 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3012 stringtable_update();
3020 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3021 proto_java_lang_ClassCastException =
3022 builtin_new(class_java_lang_ClassCastException);
3023 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3025 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3027 proto_java_lang_NullPointerException =
3028 builtin_new(class_java_lang_NullPointerException);
3029 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3030 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3032 proto_java_lang_ArrayIndexOutOfBoundsException =
3033 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3034 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3036 proto_java_lang_NegativeArraySizeException =
3037 builtin_new(class_java_lang_NegativeArraySizeException);
3038 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3040 proto_java_lang_OutOfMemoryError =
3041 builtin_new(class_java_lang_OutOfMemoryError);
3042 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3044 proto_java_lang_ArithmeticException =
3045 builtin_new(class_java_lang_ArithmeticException);
3046 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3048 proto_java_lang_ArrayStoreException =
3049 builtin_new(class_java_lang_ArrayStoreException);
3050 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3052 proto_java_lang_ThreadDeath = /* schani */
3053 builtin_new(class_java_lang_ThreadDeath);
3054 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3063 /********************* Function: loader_initclasses ****************************
3065 Initializes all loaded but uninitialized classes
3067 *******************************************************************************/
3069 void loader_initclasses ()
3073 intsDisable(); /* schani */
3075 if (makeinitializations) {
3076 c = list_first (&linkedclasses);
3079 c = list_next (&linkedclasses, c);
3083 intsRestore(); /* schani */
3086 static s4 classvalue;
3088 static void loader_compute_class_values (classinfo *c)
3092 c->vftbl->baseval = ++classvalue;
3095 while (subs != NULL) {
3096 loader_compute_class_values(subs);
3097 subs = subs->nextsub;
3099 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3104 for (i = 0; i < c->index; i++)
3106 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3107 utf_display(c->name);
3115 void loader_compute_subclasses ()
3119 intsDisable(); /* schani */
3121 c = list_first (&linkedclasses);
3123 if (!(c->flags & ACC_INTERFACE)) {
3127 c = list_next (&linkedclasses, c);
3130 c = list_first (&linkedclasses);
3132 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3133 c->nextsub = c->super->sub;
3136 c = list_next (&linkedclasses, c);
3139 loader_compute_class_values(class_java_lang_Object);
3141 intsRestore(); /* schani */
3146 /******************** function classloader_buffer ******************************
3148 sets buffer for reading classdata
3150 *******************************************************************************/
3152 void classload_buffer(u1 *buf, int len)
3155 classbuffer_size = len;
3156 classbuf_pos = buf - 1;
3160 /******************** Function: loader_close ***********************************
3164 *******************************************************************************/
3166 void loader_close ()
3170 while ( (c=list_first(&unloadedclasses)) ) {
3171 list_remove (&unloadedclasses,c);
3174 while ( (c=list_first(&unlinkedclasses)) ) {
3175 list_remove (&unlinkedclasses,c);
3178 while ( (c=list_first(&linkedclasses)) ) {
3179 list_remove (&linkedclasses,c);
3186 * These are local overrides for various environment variables in Emacs.
3187 * Please do not remove this and leave it at the end of the file, where
3188 * Emacs will automagically detect them.
3189 * ---------------------------------------------------------------------
3192 * indent-tabs-mode: t