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 689 2003-12-05 18:03:47Z stefan $
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 dolog("Warning: Can not open class file '%s'", filename);
426 /************************** function suck_stop *********************************
428 frees memory for buffer with classfile data.
429 Caution: this function may only be called if buffer has been allocated
430 by suck_start with reading a file
432 *******************************************************************************/
436 /* determine amount of classdata not retrieved by suck-operations */
438 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
440 if (classdata_left > 0) {
442 dolog("There are %d access bytes at end of classfile",
448 MFREE(classbuffer, u1, classbuffer_size);
453 /******************************************************************************/
454 /******************* Some support functions ***********************************/
455 /******************************************************************************/
459 void fprintflags (FILE *fp, u2 f)
461 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
462 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
463 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
464 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
465 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
466 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
467 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
468 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
469 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
470 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
471 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
474 /********** internal function: printflags (only for debugging) ***************/
475 void printflags (u2 f)
477 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
478 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
479 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
480 if ( f & ACC_STATIC ) printf (" STATIC");
481 if ( f & ACC_FINAL ) printf (" FINAL");
482 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
483 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
484 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
485 if ( f & ACC_NATIVE ) printf (" NATIVE");
486 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
487 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
491 /************************* Function: skipattribute *****************************
493 skips a (1) 'attribute' structure in the class file
495 *******************************************************************************/
497 static void skipattribute ()
500 skip_nbytes(suck_u4());
503 /********************** Function: skipattributebody ****************************
505 skips an attribute after the 16 bit reference to attribute_name has already
508 *******************************************************************************/
510 static void skipattributebody ()
512 skip_nbytes(suck_u4());
515 /************************* Function: skipattributes ****************************
517 skips num attribute structures
519 *******************************************************************************/
521 static void skipattributes (u4 num)
524 for (i = 0; i < num; i++)
528 /******************** function: innerclass_getconstant ************************
530 like class_getconstant, but if cptags is ZERO null is returned
532 *******************************************************************************/
534 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
536 /* invalid position in constantpool */
537 if (pos >= c->cpcount)
538 panic ("Attempt to access constant outside range");
540 /* constantpool entry of type 0 */
544 /* check type of constantpool entry */
545 if (c->cptags[pos] != ctype) {
546 error ("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
547 (int) ctype, (int) c->cptags[pos] );
550 return c->cpinfos[pos];
553 /************************ function: attribute_load ****************************
555 read attributes from classfile
557 *******************************************************************************/
559 static void attribute_load (u4 num, classinfo *c)
563 for (i = 0; i < num; i++) {
564 /* retrieve attribute name */
565 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
567 if ( aname == utf_innerclasses) {
568 /* innerclasses attribute */
570 /* skip attribute length */
572 /* number of records */
573 c->innerclasscount = suck_u2();
574 /* allocate memory for innerclass structure */
575 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
577 for (j=0;j<c->innerclasscount;j++) {
579 /* The innerclass structure contains a class with an encoded name,
580 its defining scope, its simple name and a bitmask of the access flags.
581 If an inner class is not a member, its outer_class is NULL,
582 if a class is anonymous, its name is NULL. */
584 innerclassinfo *info = c->innerclass + j;
586 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
587 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
588 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
589 info->flags = suck_u2 (); /* access_flags bitmask */
592 /* unknown attribute */
593 skipattributebody ();
598 /******************* function: checkfielddescriptor ****************************
600 checks whether a field-descriptor is valid and aborts otherwise
601 all referenced classes are inserted into the list of unloaded classes
603 *******************************************************************************/
605 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
607 char *tstart; /* pointer to start of classname */
609 char *start = utf_ptr;
611 switch (*utf_ptr++) {
625 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
626 panic ("Ill formed descriptor");
630 panic ("Ill formed descriptor");
633 /* exceeding characters */
634 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
638 /******************* function checkmethoddescriptor ****************************
640 checks whether a method-descriptor is valid and aborts otherwise.
641 All referenced classes are inserted into the list of unloaded classes.
643 *******************************************************************************/
645 static void checkmethoddescriptor (utf *d)
647 char *utf_ptr = d->text; /* current position in utf text */
648 char *end_pos = utf_end(d); /* points behind utf string */
649 char *tstart; /* pointer to start of classname */
653 /* method descriptor must start with parenthesis */
654 /* XXX check length */
655 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
657 /* XXX check length */
658 /* check arguments */
659 while ((c = *utf_ptr++) != ')') {
676 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
677 panic ("Ill formed method descriptor");
681 panic ("Ill formed methodtype-descriptor");
685 /* check returntype */
687 /* returntype void */
688 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
691 /* treat as field-descriptor */
692 checkfielddescriptor (utf_ptr,end_pos);
695 /***************** Function: print_arraydescriptor ****************************
697 Debugging helper for displaying an arraydescriptor
699 *******************************************************************************/
702 print_arraydescriptor(FILE *file,arraydescriptor *desc)
705 fprintf(file,"<NULL>");
710 if (desc->componentvftbl) {
711 if (desc->componentvftbl->class)
712 utf_fprint(file,desc->componentvftbl->class->name);
714 fprintf(file,"<no classinfo>");
720 if (desc->elementvftbl) {
721 if (desc->elementvftbl->class)
722 utf_fprint(file,desc->elementvftbl->class->name);
724 fprintf(file,"<no classinfo>");
728 fprintf(file,",%d,%d,%d,%d}",desc->arraytype,desc->dimension,
729 desc->dataoffset,desc->componentsize);
732 /******************************************************************************/
733 /************************** Functions for fields ****************************/
734 /******************************************************************************/
737 /************************ Function: field_load *********************************
739 Load everything about a class field from the class file and fill a
740 'fieldinfo' structure. For static fields, space in the data segment is
743 *******************************************************************************/
745 static void field_load (fieldinfo *f, classinfo *c)
750 f -> flags = suck_u2 (); /* ACC flags */
751 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
752 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
753 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
754 f -> offset = 0; /* offset from start of object */
758 case TYPE_INT: f->value.i = 0; break;
759 case TYPE_FLOAT: f->value.f = 0.0; break;
760 case TYPE_DOUBLE: f->value.d = 0.0; break;
761 case TYPE_ADDRESS: f->value.a = NULL;
762 heap_addreference (&(f->value.a)); /* make global reference (GC) */
766 f->value.l = 0; break;
768 f->value.l.low = 0; f->value.l.high = 0; break;
772 /* read attributes */
774 for (i=0; i<attrnum; i++) {
778 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
780 if ( aname != utf_constantvalue ) {
781 /* unknown attribute */
782 skipattributebody ();
785 /* constant value attribute */
787 /* skip attribute length */
789 /* index of value in constantpool */
792 /* initialize field with value from constantpool */
795 constant_integer *ci =
796 class_getconstant(c, pindex, CONSTANT_Integer);
797 f->value.i = ci -> value;
803 class_getconstant(c, pindex, CONSTANT_Long);
805 f->value.l = cl -> value;
811 class_getconstant(c, pindex, CONSTANT_Float);
813 f->value.f = cf->value;
818 constant_double *cd =
819 class_getconstant(c, pindex, CONSTANT_Double);
821 f->value.d = cd->value;
826 utf *u = class_getconstant(c, pindex, CONSTANT_String);
827 /* create javastring from compressed utf8-string */
828 f->value.a = literalstring_new(u);
833 log_text ("Invalid Constant - Type");
842 /********************** function: field_free **********************************/
844 static void field_free (fieldinfo *f)
850 /**************** Function: field_display (debugging only) ********************/
852 void field_display (fieldinfo *f)
855 printflags (f -> flags);
857 utf_display (f -> name);
859 utf_display (f -> descriptor);
860 printf (" offset: %ld\n", (long int) (f -> offset) );
864 /******************************************************************************/
865 /************************* Functions for methods ******************************/
866 /******************************************************************************/
869 /*********************** Function: method_load *********************************
871 Loads a method from the class file and fills an existing 'methodinfo'
872 structure. For native methods, the function pointer field is set to the
873 real function pointer, for JavaVM methods a pointer to the compiler is used
876 *******************************************************************************/
878 static void method_load (methodinfo *m, classinfo *c)
888 m -> flags = suck_u2 ();
889 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
890 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
893 m -> exceptiontable = NULL;
894 m -> entrypoint = NULL;
896 m -> stubroutine = NULL;
897 m -> methodUsed = NOTUSED;
898 m -> monoPoly = MONO;
900 m -> subRedefsUsed = 0;
904 if (! (m->flags & ACC_NATIVE) ) {
905 m -> stubroutine = createcompilerstub (m);
909 functionptr f = native_findfunction
910 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
912 m -> stubroutine = createnativestub (f, m);
918 for (i=0; i<attrnum; i++) {
921 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
923 if ( aname != utf_code) {
924 skipattributebody ();
927 if (m -> jcode) panic ("Two code-attributes for one method!");
930 m -> maxstack = suck_u2();
931 m -> maxlocals = suck_u2();
932 m -> jcodelength = suck_u4();
933 m -> jcode = MNEW (u1, m->jcodelength);
934 suck_nbytes (m->jcode, m->jcodelength);
935 m -> exceptiontablelength = suck_u2 ();
936 m -> exceptiontable =
937 MNEW (exceptiontable, m->exceptiontablelength);
940 count_vmcode_len += m->jcodelength + 18;
941 count_extable_len += 8 * m->exceptiontablelength;
944 for (e=0; e < m->exceptiontablelength; e++) {
946 m -> exceptiontable[e].startpc = suck_u2();
947 m -> exceptiontable[e].endpc = suck_u2();
948 m -> exceptiontable[e].handlerpc = suck_u2();
951 if (!idx) m -> exceptiontable[e].catchtype = NULL;
953 m -> exceptiontable[e].catchtype =
954 class_getconstant (c, idx, CONSTANT_Class);
958 skipattributes ( suck_u2() );
965 /********************* Function: method_free ***********************************
967 frees all memory that was allocated for this method
969 *******************************************************************************/
971 static void method_free (methodinfo *m)
973 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
974 if (m->exceptiontable)
975 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
976 if (m->mcode) CFREE (m->mcode, m->mcodelength);
977 if (m->stubroutine) {
978 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
979 else removecompilerstub (m->stubroutine);
984 /************** Function: method_display (debugging only) **************/
986 void method_display (methodinfo *m)
989 printflags (m -> flags);
991 utf_display (m -> name);
993 utf_display (m -> descriptor);
998 /******************** Function: method_canoverwrite ****************************
1000 Check if m and old are identical with respect to type and name. This means
1001 that old can be overwritten with m.
1003 *******************************************************************************/
1005 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1007 if (m->name != old->name) return false;
1008 if (m->descriptor != old->descriptor) return false;
1009 if (m->flags & ACC_STATIC) return false;
1016 /******************************************************************************/
1017 /************************ Functions for class *********************************/
1018 /******************************************************************************/
1021 /******************** function:: class_getconstant ******************************
1023 retrieves the value at position 'pos' of the constantpool of a class
1024 if the type of the value is other than 'ctype' the system is stopped
1026 *******************************************************************************/
1028 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1030 /* invalid position in constantpool */
1031 if (pos >= c->cpcount)
1032 panic ("Attempt to access constant outside range");
1034 /* check type of constantpool entry */
1036 if (c->cptags[pos] != ctype) {
1037 class_showconstantpool(c);
1038 error ("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1039 (int) ctype, (int) c->cptags[pos] );
1042 return c->cpinfos[pos];
1046 /********************* Function: class_constanttype ****************************
1048 Determines the type of a class entry in the ConstantPool
1050 *******************************************************************************/
1052 u4 class_constanttype (classinfo *c, u4 pos)
1054 if (pos >= c->cpcount)
1055 panic ("Attempt to access constant outside range");
1056 return c->cptags[pos];
1060 /******************** function: class_loadcpool ********************************
1062 loads the constantpool of a class,
1063 the entries are transformed into a simpler format
1064 by resolving references
1065 (a detailed overview of the compact structures can be found in global.h)
1067 *******************************************************************************/
1069 static void class_loadcpool (classinfo *c)
1072 /* The following structures are used to save information which cannot be
1073 processed during the first pass. After the complete constantpool has
1074 been traversed the references can be resolved.
1075 (only in specific order) */
1077 /* CONSTANT_Class_info entries */
1078 typedef struct forward_class {
1079 struct forward_class *next;
1084 /* CONSTANT_String */
1085 typedef struct forward_string {
1086 struct forward_string *next;
1091 /* CONSTANT_NameAndType */
1092 typedef struct forward_nameandtype {
1093 struct forward_nameandtype *next;
1097 } forward_nameandtype;
1099 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1100 typedef struct forward_fieldmethint {
1101 struct forward_fieldmethint *next;
1105 u2 nameandtype_index;
1106 } forward_fieldmethint;
1110 long int dumpsize = dump_size ();
1112 forward_class *forward_classes = NULL;
1113 forward_string *forward_strings = NULL;
1114 forward_nameandtype *forward_nameandtypes = NULL;
1115 forward_fieldmethint *forward_fieldmethints = NULL;
1117 /* number of entries in the constant_pool table */
1118 u4 cpcount = c -> cpcount = suck_u2();
1119 /* allocate memory */
1120 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1121 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1124 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1127 /* initialize constantpool */
1128 for (idx=0; idx<cpcount; idx++) {
1129 cptags[idx] = CONSTANT_UNUSED;
1130 cpinfos[idx] = NULL;
1134 /******* first pass *******/
1135 /* entries which cannot be resolved now are written into
1136 temporary structures and traversed again later */
1139 while (idx < cpcount) {
1140 /* get constant type */
1144 case CONSTANT_Class: {
1145 forward_class *nfc = DNEW(forward_class);
1147 nfc -> next = forward_classes;
1148 forward_classes = nfc;
1150 nfc -> thisindex = idx;
1151 /* reference to CONSTANT_NameAndType */
1152 nfc -> name_index = suck_u2 ();
1158 case CONSTANT_Fieldref:
1159 case CONSTANT_Methodref:
1160 case CONSTANT_InterfaceMethodref: {
1161 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1163 nff -> next = forward_fieldmethints;
1164 forward_fieldmethints = nff;
1166 nff -> thisindex = idx;
1169 /* class or interface type that contains the declaration of the field or method */
1170 nff -> class_index = suck_u2 ();
1171 /* name and descriptor of the field or method */
1172 nff -> nameandtype_index = suck_u2 ();
1178 case CONSTANT_String: {
1179 forward_string *nfs = DNEW (forward_string);
1181 nfs -> next = forward_strings;
1182 forward_strings = nfs;
1184 nfs -> thisindex = idx;
1185 /* reference to CONSTANT_Utf8_info with string characters */
1186 nfs -> string_index = suck_u2 ();
1192 case CONSTANT_NameAndType: {
1193 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1195 nfn -> next = forward_nameandtypes;
1196 forward_nameandtypes = nfn;
1198 nfn -> thisindex = idx;
1199 /* reference to CONSTANT_Utf8_info containing simple name */
1200 nfn -> name_index = suck_u2 ();
1201 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1202 nfn -> sig_index = suck_u2 ();
1208 case CONSTANT_Integer: {
1209 constant_integer *ci = NEW (constant_integer);
1212 count_const_pool_len += sizeof(constant_integer);
1215 ci -> value = suck_s4 ();
1216 cptags [idx] = CONSTANT_Integer;
1223 case CONSTANT_Float: {
1224 constant_float *cf = NEW (constant_float);
1227 count_const_pool_len += sizeof(constant_float);
1230 cf -> value = suck_float ();
1231 cptags [idx] = CONSTANT_Float;
1237 case CONSTANT_Long: {
1238 constant_long *cl = NEW(constant_long);
1241 count_const_pool_len += sizeof(constant_long);
1244 cl -> value = suck_s8 ();
1245 cptags [idx] = CONSTANT_Long;
1251 case CONSTANT_Double: {
1252 constant_double *cd = NEW(constant_double);
1255 count_const_pool_len += sizeof(constant_double);
1258 cd -> value = suck_double ();
1259 cptags [idx] = CONSTANT_Double;
1265 case CONSTANT_Utf8: {
1267 /* number of bytes in the bytes array (not string-length) */
1268 u4 length = suck_u2();
1269 cptags [idx] = CONSTANT_Utf8;
1270 /* insert utf-string into the utf-symboltable */
1271 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1272 /* skip bytes of the string */
1273 skip_nbytes(length);
1279 error ("Unkown constant type: %d",(int) t);
1287 /* resolve entries in temporary structures */
1289 while (forward_classes) {
1291 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1293 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1294 /* retrieve class from class-table */
1295 cpinfos [forward_classes -> thisindex] = class_new (name);
1297 forward_classes = forward_classes -> next;
1301 while (forward_strings) {
1303 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1305 log_text("forward_string:");
1306 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1308 log_text("\n------------------"); */
1309 /* resolve utf-string */
1310 cptags [forward_strings -> thisindex] = CONSTANT_String;
1311 cpinfos [forward_strings -> thisindex] = text;
1313 forward_strings = forward_strings -> next;
1316 while (forward_nameandtypes) {
1317 constant_nameandtype *cn = NEW (constant_nameandtype);
1320 count_const_pool_len += sizeof(constant_nameandtype);
1323 /* resolve simple name and descriptor */
1324 cn -> name = class_getconstant
1325 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1326 cn -> descriptor = class_getconstant
1327 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1329 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1330 cpinfos [forward_nameandtypes -> thisindex] = cn;
1332 forward_nameandtypes = forward_nameandtypes -> next;
1336 while (forward_fieldmethints) {
1337 constant_nameandtype *nat;
1338 constant_FMIref *fmi = NEW (constant_FMIref);
1341 count_const_pool_len += sizeof(constant_FMIref);
1343 /* resolve simple name and descriptor */
1344 nat = class_getconstant
1345 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1348 log_text("trying to resolve:");
1349 log_text(nat->name->text);
1350 switch(forward_fieldmethints ->tag) {
1351 case CONSTANT_Fieldref:
1352 log_text("CONSTANT_Fieldref");
1354 case CONSTANT_InterfaceMethodref:
1355 log_text("CONSTANT_InterfaceMethodref");
1357 case CONSTANT_Methodref:
1358 log_text("CONSTANT_Methodref");
1362 fmi -> class = class_getconstant
1363 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1364 fmi -> name = nat -> name;
1365 fmi -> descriptor = nat -> descriptor;
1367 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1368 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1370 switch (forward_fieldmethints -> tag) {
1371 case CONSTANT_Fieldref: /* check validity of descriptor */
1372 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1374 case CONSTANT_InterfaceMethodref:
1375 case CONSTANT_Methodref: /* check validity of descriptor */
1376 checkmethoddescriptor (fmi->descriptor);
1380 forward_fieldmethints = forward_fieldmethints -> next;
1384 /* class_showconstantpool(c); */
1386 dump_release (dumpsize);
1390 /********************** Function: class_load ***********************************
1392 Loads everything interesting about a class from the class file. The
1393 'classinfo' structure must have been allocated previously.
1395 The super class and the interfaces implemented by this class need not be
1396 loaded. The link is set later by the function 'class_link'.
1398 The loaded class is removed from the list 'unloadedclasses' and added to
1399 the list 'unlinkedclasses'.
1401 *******************************************************************************/
1403 static int class_load(classinfo *c)
1409 count_class_loads++;
1412 /* output for debugging purposes */
1414 char logtext[MAXLOGTEXT];
1415 sprintf(logtext, "Loading class: ");
1416 utf_sprint(logtext+strlen(logtext), c->name);
1420 /* load classdata, throw exception on error */
1422 if (!suck_start(c->name)) {
1423 throw_classnotfoundexception2(c->name);
1427 /* check signature */
1428 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1432 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1433 error ("File version %d.%d is not supported",
1434 (int) ma, (int) mi);
1437 class_loadcpool (c);
1439 c->erroneous_state=0;
1440 c->initializing_thread=0;
1442 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1443 c -> impldBy = NULL;
1446 c -> flags = suck_u2 ();
1450 /* retrieve superclass */
1451 if ( (i = suck_u2 () ) ) {
1452 c -> super = class_getconstant (c, i, CONSTANT_Class);
1458 /* retrieve interfaces */
1459 c -> interfacescount = suck_u2 ();
1460 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1461 for (i=0; i < c -> interfacescount; i++) {
1462 c -> interfaces [i] =
1463 class_getconstant (c, suck_u2(), CONSTANT_Class);
1467 c -> fieldscount = suck_u2 ();
1468 /* utf_display(c->name);
1469 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1471 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1472 for (i=0; i < c -> fieldscount; i++) {
1473 field_load (&(c->fields[i]), c);
1477 c -> methodscount = suck_u2 ();
1478 c -> methods = MNEW (methodinfo, c -> methodscount);
1479 for (i=0; i < c -> methodscount; i++) {
1480 method_load (&(c -> methods [i]), c);
1484 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1485 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1486 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1489 /* load variable-length attribute structures */
1490 attribute_load (suck_u2(), c);
1495 /* remove class from list of unloaded classes and
1496 add to list of unlinked classes */
1497 list_remove (&unloadedclasses, c);
1498 list_addlast (&unlinkedclasses, c);
1505 /************** internal Function: class_highestinterface ***********************
1507 Used by the function class_link to determine the amount of memory needed
1508 for the interface table.
1510 *******************************************************************************/
1512 static s4 class_highestinterface (classinfo *c)
1517 if ( ! (c->flags & ACC_INTERFACE) ) {
1518 char logtext[MAXLOGTEXT];
1519 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1520 utf_sprint (logtext+strlen(logtext), c->name);
1525 for (i=0; i<c->interfacescount; i++) {
1526 s4 h2 = class_highestinterface (c->interfaces[i]);
1533 /* class_addinterface **********************************************************
1535 Is needed by class_link for adding a VTBL to a class. All interfaces
1536 implemented by ic are added as well.
1538 *******************************************************************************/
1540 static void class_addinterface (classinfo *c, classinfo *ic)
1544 vftbl *vftbl = c->vftbl;
1546 if (i >= vftbl->interfacetablelength)
1547 panic ("Inernal error: interfacetable overflow");
1548 if (vftbl->interfacetable[-i])
1551 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1552 vftbl->interfacevftbllength[i] = 1;
1553 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1554 vftbl->interfacetable[-i][0] = NULL;
1557 vftbl->interfacevftbllength[i] = ic->methodscount;
1558 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1561 count_vftbl_len += sizeof(methodptr) *
1562 (ic->methodscount + (ic->methodscount == 0));
1565 for (j=0; j<ic->methodscount; j++) {
1568 for (m = 0; m < sc->methodscount; m++) {
1569 methodinfo *mi = &(sc->methods[m]);
1570 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1571 vftbl->interfacetable[-i][j] =
1572 vftbl->table[mi->vftblindex];
1582 for (j = 0; j < ic->interfacescount; j++)
1583 class_addinterface(c, ic->interfaces[j]);
1587 /******************* Function: class_new_array *********************************
1589 This function is called by class_new to setup an array class.
1591 *******************************************************************************/
1594 class_new_array(classinfo *c)
1596 classinfo *comp = NULL;
1600 /* Array classes are not loaded from classfiles. */
1601 list_remove (&unloadedclasses, c);
1603 /* Check array class name */
1604 namelen = c->name->blength;
1605 if (namelen < 2 || c->name->text[0] != '[')
1606 panic("Invalid array class name.");
1608 /* Check the component type */
1609 switch (c->name->text[1]) {
1611 /* c is an array of arrays. We have to create the component class. */
1612 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1616 /* c is an array of objects. */
1617 if (namelen < 4 || c->name->text[namelen-1] != ';')
1618 panic("Invalid array class name.");
1619 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1623 /* Setup the array class */
1624 c->super = class_java_lang_Object;
1626 c->interfacescount = 2;
1627 c->interfaces = MNEW(classinfo*,2);
1628 c->interfaces[0] = class_java_lang_Cloneable;
1629 c->interfaces[1] = class_java_io_Serializable;
1631 c->methodscount = 1;
1632 c->methods = MNEW (methodinfo, c->methodscount);
1635 memset(clone,0,sizeof(methodinfo));
1636 clone->flags = ACC_PUBLIC; /* XXX protected? */
1637 clone->name = utf_new_char("clone");
1638 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1640 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1641 clone->monoPoly = MONO; /* XXX should be poly? */
1643 /* XXX: field: length? */
1645 /* The array class has to be linked */
1646 list_addlast(&unlinkedclasses,c);
1649 * Array classes which are created after the other classes have been
1650 * loaded and linked are linked explicitely.
1655 loader_load(c->name);
1658 /****************** Function: class_link_array *********************************
1660 This function is called by class_link to create the
1661 arraydescriptor for an array class.
1663 This function returns NULL if the array cannot be linked because
1664 the component type has not been linked yet.
1666 *******************************************************************************/
1670 class_link_array(classinfo *c)
1672 classinfo *comp = NULL;
1673 int namelen = c->name->blength;
1674 arraydescriptor *desc;
1677 /* Check the component type */
1678 switch (c->name->text[1]) {
1680 /* c is an array of arrays. */
1681 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1682 if (!comp) panic("Could not find component array class.");
1686 /* c is an array of objects. */
1687 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1688 if (!comp) panic("Could not find component class.");
1692 /* If the component type has not been linked return NULL */
1693 if (comp && !comp->linked)
1696 /* Allocate the arraydescriptor */
1697 desc = NEW(arraydescriptor);
1700 /* c is an array of references */
1701 desc->arraytype = ARRAYTYPE_OBJECT;
1702 desc->componentsize = sizeof(void*);
1703 desc->dataoffset = OFFSET(java_objectarray,data);
1705 compvftbl = comp->vftbl;
1707 panic("Component class has no vftbl.");
1708 desc->componentvftbl = compvftbl;
1710 if (compvftbl->arraydesc) {
1711 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1712 desc->dimension = compvftbl->arraydesc->dimension + 1;
1713 desc->elementtype = compvftbl->arraydesc->elementtype;
1716 desc->elementvftbl = compvftbl;
1717 desc->dimension = 1;
1718 desc->elementtype = ARRAYTYPE_OBJECT;
1722 /* c is an array of a primitive type */
1723 switch (c->name->text[1]) {
1724 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1725 desc->dataoffset = OFFSET(java_booleanarray,data);
1726 desc->componentsize = sizeof(u1); break;
1727 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1728 desc->dataoffset = OFFSET(java_bytearray,data);
1729 desc->componentsize = sizeof(u1); break;
1730 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1731 desc->dataoffset = OFFSET(java_chararray,data);
1732 desc->componentsize = sizeof(u2); break;
1733 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1734 desc->dataoffset = OFFSET(java_doublearray,data);
1735 desc->componentsize = sizeof(double); break;
1736 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1737 desc->dataoffset = OFFSET(java_floatarray,data);
1738 desc->componentsize = sizeof(float); break;
1739 case 'I': desc->arraytype = ARRAYTYPE_INT;
1740 desc->dataoffset = OFFSET(java_intarray,data);
1741 desc->componentsize = sizeof(s4); break;
1742 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1743 desc->dataoffset = OFFSET(java_longarray,data);
1744 desc->componentsize = sizeof(s8); break;
1745 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1746 desc->dataoffset = OFFSET(java_shortarray,data);
1747 desc->componentsize = sizeof(s2); break;
1749 panic("Invalid array class name");
1752 desc->componentvftbl = NULL;
1753 desc->elementvftbl = NULL;
1754 desc->dimension = 1;
1755 desc->elementtype = desc->arraytype;
1761 /********************** Function: class_link ***********************************
1763 Tries to link a class. The super class and every implemented interface must
1764 already have been linked. The function calculates the length in bytes that
1765 an instance of this class requires as well as the VTBL for methods and
1768 If the class can be linked, it is removed from the list 'unlinkedclasses'
1769 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1772 Attention: If cyclical class definitions are encountered, the program gets
1773 into an infinite loop (we'll have to work that out)
1775 *******************************************************************************/
1777 void class_link(classinfo *c)
1779 s4 supervftbllength; /* vftbllegnth of super class */
1780 s4 vftbllength; /* vftbllength of current class */
1781 s4 interfacetablelength; /* interface table length */
1782 classinfo *super = c->super; /* super class */
1783 classinfo *ic, *c2; /* intermediate class variables */
1784 vftbl *v; /* vftbl of current class */
1785 s4 i; /* interface/method/field counter */
1786 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1789 /* check if all superclasses are already linked, if not put c at end of
1790 unlinked list and return. Additionally initialize class fields. */
1792 /* check interfaces */
1794 for (i = 0; i < c->interfacescount; i++) {
1795 ic = c->interfaces[i];
1797 list_remove(&unlinkedclasses, c);
1798 list_addlast(&unlinkedclasses, c);
1803 /* check super class */
1805 if (super == NULL) { /* class java.long.Object */
1807 c->classUsed = USED; /* Object class is always used CO-RT*/
1808 c -> impldBy = NULL;
1809 c->instancesize = sizeof(java_objectheader);
1811 vftbllength = supervftbllength = 0;
1813 c->finalizer = NULL;
1816 if (!super->linked) {
1817 list_remove(&unlinkedclasses, c);
1818 list_addlast(&unlinkedclasses, c);
1822 /* handle array classes */
1823 if (c->name->text[0] == '[')
1824 if ((arraydesc = class_link_array(c)) == NULL) {
1825 list_remove(&unlinkedclasses, c);
1826 list_addlast(&unlinkedclasses, c);
1830 if (c->flags & ACC_INTERFACE)
1831 c->index = interfaceindex++;
1833 c->index = super->index + 1;
1835 c->instancesize = super->instancesize;
1837 vftbllength = supervftbllength = super->vftbl->vftbllength;
1839 c->finalizer = super->finalizer;
1844 char logtext[MAXLOGTEXT];
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 char logtext[MAXLOGTEXT];
2380 sprintf (logtext, "Class ");
2381 utf_sprint (logtext+strlen(logtext), c->name);
2382 sprintf (logtext+strlen(logtext), " has no initializer");
2385 /* goto callinitialize;*/
2389 if (! (m->flags & ACC_STATIC))
2390 panic ("Class initializer is not static!");
2393 char logtext[MAXLOGTEXT];
2394 sprintf (logtext, "Starting initializer for class: ");
2395 utf_sprint (logtext+strlen(logtext), c->name);
2404 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2407 assert(blockInts == 0);
2412 printf ("#### Initializer of ");
2413 utf_display (c->name);
2414 printf (" has thrown: ");
2415 utf_display (exceptionptr->vftbl->class->name);
2421 char logtext[MAXLOGTEXT];
2422 sprintf (logtext, "Finished initializer for class: ");
2423 utf_sprint (logtext+strlen(logtext), c->name);
2426 if (c->name == utf_systemclass) {
2427 /* class java.lang.System requires explicit initialization */
2430 printf ("#### Initializing class System");
2432 /* find initializing method */
2433 m = class_findmethod (c,
2434 utf_initsystemclass,
2438 /* no method found */
2439 /* printf("initializeSystemClass failed"); */
2447 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2450 assert(blockInts == 0);
2455 printf ("#### initializeSystemClass has thrown: ");
2456 utf_display (exceptionptr->vftbl->class->name);
2467 /********* Function: find_class_method_constant *********/
2468 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2473 for (i=0; i<c->cpcount; i++) {
2475 e = c -> cpinfos [i];
2478 switch (c -> cptags [i]) {
2479 case CONSTANT_Methodref:
2481 constant_FMIref *fmi = e;
2482 if ( (fmi->class->name == c1)
2483 && (fmi->name == m1)
2484 && (fmi->descriptor == d1)) {
2491 case CONSTANT_InterfaceMethodref:
2493 constant_FMIref *fmi = e;
2494 if ( (fmi->class->name == c1)
2495 && (fmi->name == m1)
2496 && (fmi->descriptor == d1)) {
2510 void class_showconstanti(classinfo *c, int ii)
2516 printf ("#%d: ", (int) i);
2518 switch (c->cptags [i]) {
2519 case CONSTANT_Class:
2520 printf("Classreference -> ");
2521 utf_display(((classinfo*)e)->name);
2524 case CONSTANT_Fieldref:
2525 printf("Fieldref -> "); goto displayFMIi;
2526 case CONSTANT_Methodref:
2527 printf("Methodref -> "); goto displayFMIi;
2528 case CONSTANT_InterfaceMethodref:
2529 printf("InterfaceMethod -> "); goto displayFMIi;
2532 constant_FMIref *fmi = e;
2533 utf_display(fmi->class->name);
2535 utf_display(fmi->name);
2537 utf_display(fmi->descriptor);
2541 case CONSTANT_String:
2542 printf("String -> ");
2545 case CONSTANT_Integer:
2546 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2548 case CONSTANT_Float:
2549 printf("Float -> %f", ((constant_float*)e)->value);
2551 case CONSTANT_Double:
2552 printf("Double -> %f", ((constant_double*)e)->value);
2556 u8 v = ((constant_long*)e)->value;
2558 printf("Long -> %ld", (long int) v);
2560 printf("Long -> HI: %ld, LO: %ld\n",
2561 (long int) v.high, (long int) v.low);
2565 case CONSTANT_NameAndType:
2567 constant_nameandtype *cnt = e;
2568 printf("NameAndType: ");
2569 utf_display(cnt->name);
2571 utf_display(cnt->descriptor);
2579 panic("Invalid type of ConstantPool-Entry");
2586 void class_showconstantpool (classinfo *c)
2591 printf ("---- dump of constant pool ----\n");
2593 for (i=0; i<c->cpcount; i++) {
2594 printf ("#%d: ", (int) i);
2596 e = c -> cpinfos [i];
2599 switch (c -> cptags [i]) {
2600 case CONSTANT_Class:
2601 printf ("Classreference -> ");
2602 utf_display ( ((classinfo*)e) -> name );
2605 case CONSTANT_Fieldref:
2606 printf ("Fieldref -> "); goto displayFMI;
2607 case CONSTANT_Methodref:
2608 printf ("Methodref -> "); goto displayFMI;
2609 case CONSTANT_InterfaceMethodref:
2610 printf ("InterfaceMethod -> "); goto displayFMI;
2613 constant_FMIref *fmi = e;
2614 utf_display ( fmi->class->name );
2616 utf_display ( fmi->name);
2618 utf_display ( fmi->descriptor );
2622 case CONSTANT_String:
2623 printf ("String -> ");
2626 case CONSTANT_Integer:
2627 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2629 case CONSTANT_Float:
2630 printf ("Float -> %f", ((constant_float*)e) -> value);
2632 case CONSTANT_Double:
2633 printf ("Double -> %f", ((constant_double*)e) -> value);
2637 u8 v = ((constant_long*)e) -> value;
2639 printf ("Long -> %ld", (long int) v);
2641 printf ("Long -> HI: %ld, LO: %ld\n",
2642 (long int) v.high, (long int) v.low);
2646 case CONSTANT_NameAndType:
2648 constant_nameandtype *cnt = e;
2649 printf ("NameAndType: ");
2650 utf_display (cnt->name);
2652 utf_display (cnt->descriptor);
2656 printf ("Utf8 -> ");
2660 panic ("Invalid type of ConstantPool-Entry");
2670 /********** Function: class_showmethods (debugging only) *************/
2672 void class_showmethods (classinfo *c)
2676 printf ("--------- Fields and Methods ----------------\n");
2677 printf ("Flags: "); printflags (c->flags); printf ("\n");
2679 printf ("This: "); utf_display (c->name); printf ("\n");
2681 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2683 printf ("Index: %d\n", c->index);
2685 printf ("interfaces:\n");
2686 for (i=0; i < c-> interfacescount; i++) {
2688 utf_display (c -> interfaces[i] -> name);
2689 printf (" (%d)\n", c->interfaces[i] -> index);
2692 printf ("fields:\n");
2693 for (i=0; i < c -> fieldscount; i++) {
2694 field_display (&(c -> fields[i]));
2697 printf ("methods:\n");
2698 for (i=0; i < c -> methodscount; i++) {
2699 methodinfo *m = &(c->methods[i]);
2700 if ( !(m->flags & ACC_STATIC))
2701 printf ("vftblindex: %d ", m->vftblindex);
2703 method_display ( m );
2707 printf ("Virtual function table:\n");
2708 for (i=0; i<c->vftbl->vftbllength; i++) {
2709 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2716 /******************************************************************************/
2717 /******************* General functions for the class loader *******************/
2718 /******************************************************************************/
2720 /********************* Function: loader_load ***********************************
2722 Loads and links the class desired class and each class and interface
2724 Returns: a pointer to this class
2726 *******************************************************************************/
2728 static int loader_load_running = 0;
2730 classinfo *loader_load (utf *topname)
2734 long int starttime=0,stoptime=0;
2736 /* avoid recursive calls */
2737 if (loader_load_running)
2738 return class_new(topname);
2739 loader_load_running++;
2741 intsDisable(); /* schani */
2744 starttime = getcputime();
2746 top = class_new (topname);
2749 while ( (c = list_first(&unloadedclasses)) ) {
2750 if (!class_load (c)) {
2751 list_remove (&unloadedclasses, c);
2757 while ( (c = list_first(&unlinkedclasses)) ) {
2762 loader_compute_subclasses();
2765 if (getloadingtime) {
2766 stoptime = getcputime();
2767 loadingtime += (stoptime-starttime);
2771 loader_load_running--;
2773 /* check if a former loader_load call tried to load/link the class and failed.
2774 This is needed because the class didn't appear in the undloadclasses or unlinkedclasses list during this class; */
2777 throw_classnotfoundexception2(top->name);
2779 } else if (!top->linked) {
2780 throw_linkageerror2(top->name);
2785 intsRestore(); /* schani */
2791 /**************** function: create_primitive_classes ***************************
2793 create classes representing primitive types
2795 ********************************************************************************/
2798 void create_primitive_classes()
2802 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2803 /* create primitive class */
2804 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2805 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2806 c -> impldBy = NULL;
2808 /* prevent loader from loading primitive class */
2809 list_remove (&unloadedclasses, c);
2811 /* add to unlinked classes */
2812 list_addlast (&unlinkedclasses, c);
2813 c -> super = class_java_lang_Object;
2816 primitivetype_table[i].class_primitive = c;
2818 /* create class for wrapping the primitive type */
2819 primitivetype_table[i].class_wrap =
2820 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2821 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2822 primitivetype_table[i].class_wrap -> impldBy = NULL;
2824 /* create the primitive array class */
2825 if (primitivetype_table[i].arrayname) {
2826 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2827 primitivetype_table[i].arrayclass = c;
2829 if (!c->linked) class_link(c);
2830 primitivetype_table[i].arrayvftbl = c->vftbl;
2835 /**************** function: class_primitive_from_sig ***************************
2837 return the primitive class indicated by the given signature character
2839 If the descriptor does not indicate a valid primitive type the
2840 return value is NULL.
2842 ********************************************************************************/
2844 classinfo *class_primitive_from_sig(char sig)
2847 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2848 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2849 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2850 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2851 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2852 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2853 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2854 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2855 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2860 /****************** function: class_from_descriptor ****************************
2862 return the class indicated by the given descriptor
2864 utf_ptr....first character of descriptor
2865 end_ptr....first character after the end of the string
2866 next.......if non-NULL, *next is set to the first character after
2868 mode.......what to do if a class descriptor is parsed successfully:
2869 CLASSLOAD_SKIP...skip it and return something != NULL
2870 CLASSLOAD_NEW....get classinfo * via class_new
2871 CLASSLOAD_LOAD...get classinfo * via loader_load
2873 If the descriptor is invalid the return value is NULL
2875 ********************************************************************************/
2877 classinfo *class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
2879 char *start = utf_ptr;
2883 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
2884 if (error) return NULL;
2885 if (next) *next = utf_ptr;
2893 if (mode == CLASSLOAD_SKIP) return class_java_lang_Object;
2894 name = utf_new(start,utf_ptr-start);
2895 return (mode == CLASSLOAD_LOAD) ? loader_load(name) : class_new(name);
2897 return class_primitive_from_sig(*start);
2901 /*************** function: create_pseudo_classes *******************************
2903 create pseudo classes used by the typechecker
2905 ********************************************************************************/
2908 create_pseudo_classes()
2910 /* pseudo class for Arraystubs (extends java.lang.Object) */
2912 pseudo_class_Arraystub = class_new( utf_new_char("$ARRAYSTUB$") );
2913 list_remove(&unloadedclasses,pseudo_class_Arraystub);
2915 pseudo_class_Arraystub->super = class_java_lang_Object;
2916 pseudo_class_Arraystub->interfacescount = 2;
2917 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
2918 pseudo_class_Arraystub->interfaces[0] =
2919 class_java_lang_Cloneable;
2920 pseudo_class_Arraystub->interfaces[1] =
2921 class_java_io_Serializable;
2923 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
2924 class_link(pseudo_class_Arraystub);
2926 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
2928 /* pseudo class representing the null type */
2930 pseudo_class_Null = class_new( utf_new_char("$NULL$") );
2931 list_remove(&unloadedclasses,pseudo_class_Null);
2933 pseudo_class_Null->super = class_java_lang_Object;
2935 list_addlast(&unlinkedclasses,pseudo_class_Null);
2936 class_link(pseudo_class_Null);
2939 /********************** Function: loader_init **********************************
2941 Initializes all lists and loads all classes required for the system or the
2944 *******************************************************************************/
2946 void loader_init (u1 * stackbottom)
2951 log_text("Entering loader_init");
2954 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2955 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2956 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2958 /* create utf-symbols for pointer comparison of frequently used strings */
2959 utf_innerclasses = utf_new_char("InnerClasses");
2960 utf_constantvalue = utf_new_char("ConstantValue");
2961 utf_code = utf_new_char("Code");
2962 utf_finalize = utf_new_char("finalize");
2963 utf_fidesc = utf_new_char("()V");
2964 utf_clinit = utf_new_char("<clinit>");
2965 utf_initsystemclass = utf_new_char("initializeSystemClass");
2966 utf_systemclass = utf_new_char("java/lang/System");
2967 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
2968 utf_initialize =utf_new_char("initialize");
2969 utf_initializedesc =utf_new_char("(I)V");
2971 utf_vmclass =utf_new_char("java/lang/VMClass");
2973 /* create some important classes */
2974 /* These classes have to be created now because the classinfo
2975 * pointers are used in the loading code.
2977 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
2978 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
2979 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
2980 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
2982 log_text("loader_init: java/lang/Object");
2983 /* load the classes which were created above */
2984 loader_load (class_java_lang_Object->name);
2986 loader_inited=1; /*JOWENN*/
2988 class_java_lang_Throwable =
2989 loader_load( utf_new_char("java/lang/Throwable") );
2991 log_text("loader_init: loader_load: java/lang/ClassCastException");
2992 class_java_lang_ClassCastException =
2993 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2994 class_java_lang_NullPointerException =
2995 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2996 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2997 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2998 class_java_lang_NegativeArraySizeException = loader_load (
2999 utf_new_char ("java/lang/NegativeArraySizeException") );
3000 class_java_lang_OutOfMemoryError = loader_load (
3001 utf_new_char ("java/lang/OutOfMemoryError") );
3002 class_java_lang_ArrayStoreException =
3003 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
3004 class_java_lang_ArithmeticException =
3005 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
3006 class_java_lang_ThreadDeath = /* schani */
3007 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
3008 /* create classes representing primitive types */
3009 create_primitive_classes();
3011 /* create classes used by the typechecker */
3012 create_pseudo_classes();
3014 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3015 stringtable_update();
3023 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3024 proto_java_lang_ClassCastException =
3025 builtin_new(class_java_lang_ClassCastException);
3026 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3028 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3030 proto_java_lang_NullPointerException =
3031 builtin_new(class_java_lang_NullPointerException);
3032 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3033 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3035 proto_java_lang_ArrayIndexOutOfBoundsException =
3036 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3037 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3039 proto_java_lang_NegativeArraySizeException =
3040 builtin_new(class_java_lang_NegativeArraySizeException);
3041 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3043 proto_java_lang_OutOfMemoryError =
3044 builtin_new(class_java_lang_OutOfMemoryError);
3045 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3047 proto_java_lang_ArithmeticException =
3048 builtin_new(class_java_lang_ArithmeticException);
3049 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3051 proto_java_lang_ArrayStoreException =
3052 builtin_new(class_java_lang_ArrayStoreException);
3053 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3055 proto_java_lang_ThreadDeath = /* schani */
3056 builtin_new(class_java_lang_ThreadDeath);
3057 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3066 /********************* Function: loader_initclasses ****************************
3068 Initializes all loaded but uninitialized classes
3070 *******************************************************************************/
3072 void loader_initclasses ()
3076 intsDisable(); /* schani */
3078 if (makeinitializations) {
3079 c = list_first (&linkedclasses);
3082 c = list_next (&linkedclasses, c);
3086 intsRestore(); /* schani */
3089 static s4 classvalue;
3091 static void loader_compute_class_values (classinfo *c)
3095 c->vftbl->baseval = ++classvalue;
3098 while (subs != NULL) {
3099 loader_compute_class_values(subs);
3100 subs = subs->nextsub;
3102 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3107 for (i = 0; i < c->index; i++)
3109 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3110 utf_display(c->name);
3118 void loader_compute_subclasses ()
3122 intsDisable(); /* schani */
3124 c = list_first (&linkedclasses);
3126 if (!(c->flags & ACC_INTERFACE)) {
3130 c = list_next (&linkedclasses, c);
3133 c = list_first (&linkedclasses);
3135 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3136 c->nextsub = c->super->sub;
3139 c = list_next (&linkedclasses, c);
3142 loader_compute_class_values(class_java_lang_Object);
3144 intsRestore(); /* schani */
3149 /******************** function classloader_buffer ******************************
3151 sets buffer for reading classdata
3153 *******************************************************************************/
3155 void classload_buffer(u1 *buf, int len)
3158 classbuffer_size = len;
3159 classbuf_pos = buf - 1;
3163 /******************** Function: loader_close ***********************************
3167 *******************************************************************************/
3169 void loader_close ()
3173 while ( (c=list_first(&unloadedclasses)) ) {
3174 list_remove (&unloadedclasses,c);
3177 while ( (c=list_first(&unlinkedclasses)) ) {
3178 list_remove (&unlinkedclasses,c);
3181 while ( (c=list_first(&linkedclasses)) ) {
3182 list_remove (&linkedclasses,c);
3189 * These are local overrides for various environment variables in Emacs.
3190 * Please do not remove this and leave it at the end of the file, where
3191 * Emacs will automagically detect them.
3192 * ---------------------------------------------------------------------
3195 * indent-tabs-mode: t