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 673 2003-11-23 22:14:35Z 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;
116 /* important system classes ***************************************************/
118 classinfo *class_java_lang_Object;
119 classinfo *class_java_lang_String;
121 classinfo *class_java_lang_Throwable;
122 classinfo *class_java_lang_Cloneable;
123 classinfo *class_java_io_Serializable;
125 /* Pseudo classes for the typechecker */
126 classinfo *pseudo_class_Arraystub = NULL;
127 classinfo *pseudo_class_Null = NULL;
128 vftbl *pseudo_class_Arraystub_vftbl = NULL;
131 /* These are made static so they cannot be used for throwing in native */
133 static classinfo *class_java_lang_ClassCastException;
134 static classinfo *class_java_lang_NullPointerException;
135 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
136 static classinfo *class_java_lang_NegativeArraySizeException;
137 static classinfo *class_java_lang_OutOfMemoryError;
138 static classinfo *class_java_lang_ArithmeticException;
139 static classinfo *class_java_lang_ArrayStoreException;
140 static classinfo *class_java_lang_ThreadDeath;
142 static methodinfo method_clone_array;
144 static int loader_inited = 0;
146 /******************************************************************************
148 structure for primitive classes: contains the class for wrapping the
149 primitive type, the primitive class, the name of the class for wrapping,
150 the one character type signature and the name of the primitive class
152 ******************************************************************************/
154 /* CAUTION: Don't change the order of the types. This table is indexed
155 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
157 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
158 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
159 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
160 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
161 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
162 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
163 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
164 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
165 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
166 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }};
168 /* instances of important system classes **************************************/
170 java_objectheader *proto_java_lang_ClassCastException;
171 java_objectheader *proto_java_lang_NullPointerException;
172 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
173 java_objectheader *proto_java_lang_NegativeArraySizeException;
174 java_objectheader *proto_java_lang_OutOfMemoryError;
175 java_objectheader *proto_java_lang_ArithmeticException;
176 java_objectheader *proto_java_lang_ArrayStoreException;
177 java_objectheader *proto_java_lang_ThreadDeath;
179 /************* functions for reading classdata *********************************
181 getting classdata in blocks of variable size
182 (8,16,32,64-bit integer or float)
184 *******************************************************************************/
186 static char *classpath = ""; /* searchpath for classfiles */
187 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
188 static u1 *classbuf_pos; /* current position in classfile buffer */
189 static int classbuffer_size; /* size of classfile-data */
191 /* transfer block of classfile data into a buffer */
193 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
196 /* skip block of classfile data */
198 #define skip_nbytes(len) classbuf_pos+=len;
202 return *++classbuf_pos;
206 u1 a=suck_u1(), b=suck_u1();
207 return ((u2)a<<8)+(u2)b;
211 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
212 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
214 #define suck_s8() (s8) suck_u8()
215 #define suck_s2() (s2) suck_u2()
216 #define suck_s4() (s4) suck_u4()
217 #define suck_s1() (s1) suck_u1()
220 /* get u8 from classfile data */
228 return (hi<<32) + lo;
237 /* get float from classfile data */
239 static float suck_float ()
246 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
247 memcpy ( (u1*) (&f), buffer, 4);
249 suck_nbytes ( (u1*) (&f), 4 );
252 PANICIF (sizeof(float) != 4, "Incompatible float-format");
257 /* get double from classfile data */
258 static double suck_double ()
265 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
266 memcpy ( (u1*) (&d), buffer, 8);
268 suck_nbytes ( (u1*) (&d), 8 );
271 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
276 /************************** function suck_init *********************************
278 called once at startup, sets the searchpath for the classfiles
280 *******************************************************************************/
282 void suck_init (char *cpath)
289 /************************** function suck_start ********************************
291 returns true if classbuffer is already loaded or a file for the
292 specified class has succussfully been read in. All directories of
293 the searchpath are used to find the classfile (<classname>.class).
294 Returns false if no classfile is found and writes an error message.
296 *******************************************************************************/
299 bool suck_start (utf *classname) {
301 #define MAXFILENAME 1000 /* maximum length of a filename */
303 char filename[MAXFILENAME+10]; /* room for '.class' */
304 char *pathpos; /* position in searchpath */
305 char c, *utf_ptr; /* pointer to the next utf8-character */
307 int filenamelen, err;
311 if (classbuffer) /* classbuffer is already valid */
318 /* skip path separator */
320 while (*pathpos == ':')
323 /* extract directory from searchpath */
326 while ((*pathpos) && (*pathpos!=':')) {
327 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
328 filename[filenamelen++] = *(pathpos++);
333 if ( ((filename[filenamelen-1]=='p') || (filename[filenamelen-1]=='P')) &
334 ((filename[filenamelen-2]=='i') || (filename[filenamelen-1]=='I')) &
335 ((filename[filenamelen-3]=='z') || (filename[filenamelen-1]=='Z')) ) {
343 filename[filenamelen++]='\0';
344 if (uf==0) uf=unzOpen(filename);
346 utf_ptr = classname->text;
348 while (utf_ptr < utf_end(classname)) {
349 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
351 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
353 filename[filenamelen++] = c;
355 strcpy (filename+filenamelen, ".class");
356 if (cacao_locate(uf,classname)==UNZ_OK) {
357 unz_file_info file_info;
358 log_text("Class found in zip file");
359 if (unzGetCurrentFileInfo(uf,&file_info,filename,
360 sizeof(filename),NULL,0,NULL,0) ==UNZ_OK) {
361 if (unzOpenCurrentFile(uf)==UNZ_OK) {
362 classbuffer_size = file_info.uncompressed_size;
363 classbuffer = MNEW(u1, classbuffer_size);
364 classbuf_pos = classbuffer-1;
365 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
366 if (unzReadCurrentFile(uf,classbuffer,classbuffer_size)==classbuffer_size) {
367 unzCloseCurrentFile(uf);
370 MFREE(classbuffer,u1,classbuffer_size);
371 log_text("Error while unzipping");
373 } else log_text("Error while opening file in archive");
374 } else log_text("Error while retrieving fileinfo");
376 unzCloseCurrentFile(uf);
381 filename[filenamelen++] = '/';
383 /* add classname to filename */
385 utf_ptr = classname->text;
386 while (utf_ptr < utf_end(classname)) {
387 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
389 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
391 filename[filenamelen++] = c;
396 strcpy (filename+filenamelen, ".class");
398 classfile = fopen(filename, "r");
399 if (classfile) { /* file exists */
401 /* determine size of classfile */
403 err = stat (filename, &buffer);
405 if (!err) { /* read classfile data */
406 classbuffer_size = buffer.st_size;
407 classbuffer = MNEW(u1, classbuffer_size);
408 classbuf_pos = classbuffer-1;
409 fread(classbuffer, 1, classbuffer_size, classfile);
417 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
425 /************************** function suck_stop *********************************
427 frees memory for buffer with classfile data.
428 Caution: this function may only be called if buffer has been allocated
429 by suck_start with reading a file
431 *******************************************************************************/
435 /* determine amount of classdata not retrieved by suck-operations */
437 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
439 if (classdata_left > 0) {
441 sprintf (logtext,"There are %d access bytes at end of classfile",
448 MFREE(classbuffer, u1, classbuffer_size);
452 /******************************************************************************/
453 /******************* Some support functions ***********************************/
454 /******************************************************************************/
458 void fprintflags (FILE *fp, u2 f)
460 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
461 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
462 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
463 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
464 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
465 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
466 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
467 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
468 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
469 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
470 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
473 /********** internal function: printflags (only for debugging) ***************/
474 void printflags (u2 f)
476 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
477 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
478 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
479 if ( f & ACC_STATIC ) printf (" STATIC");
480 if ( f & ACC_FINAL ) printf (" FINAL");
481 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
482 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
483 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
484 if ( f & ACC_NATIVE ) printf (" NATIVE");
485 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
486 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
490 /************************* Function: skipattribute *****************************
492 skips a (1) 'attribute' structure in the class file
494 *******************************************************************************/
496 static void skipattribute ()
499 skip_nbytes(suck_u4());
502 /********************** Function: skipattributebody ****************************
504 skips an attribute after the 16 bit reference to attribute_name has already
507 *******************************************************************************/
509 static void skipattributebody ()
511 skip_nbytes(suck_u4());
514 /************************* Function: skipattributes ****************************
516 skips num attribute structures
518 *******************************************************************************/
520 static void skipattributes (u4 num)
523 for (i = 0; i < num; i++)
527 /******************** function: innerclass_getconstant ************************
529 like class_getconstant, but if cptags is ZERO null is returned
531 *******************************************************************************/
533 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
535 /* invalid position in constantpool */
536 if (pos >= c->cpcount)
537 panic ("Attempt to access constant outside range");
539 /* constantpool entry of type 0 */
543 /* check type of constantpool entry */
544 if (c->cptags[pos] != ctype) {
545 sprintf (logtext, "Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
546 (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 sprintf (logtext, "Type mismatch on constant: %d requested, %d here (class_getconstant)",
1039 (int) ctype, (int) c->cptags[pos] );
1043 return c->cpinfos[pos];
1047 /********************* Function: class_constanttype ****************************
1049 Determines the type of a class entry in the ConstantPool
1051 *******************************************************************************/
1053 u4 class_constanttype (classinfo *c, u4 pos)
1055 if (pos >= c->cpcount)
1056 panic ("Attempt to access constant outside range");
1057 return c->cptags[pos];
1061 /******************** function: class_loadcpool ********************************
1063 loads the constantpool of a class,
1064 the entries are transformed into a simpler format
1065 by resolving references
1066 (a detailed overview of the compact structures can be found in global.h)
1068 *******************************************************************************/
1070 static void class_loadcpool (classinfo *c)
1073 /* The following structures are used to save information which cannot be
1074 processed during the first pass. After the complete constantpool has
1075 been traversed the references can be resolved.
1076 (only in specific order) */
1078 /* CONSTANT_Class_info entries */
1079 typedef struct forward_class {
1080 struct forward_class *next;
1085 /* CONSTANT_String */
1086 typedef struct forward_string {
1087 struct forward_string *next;
1092 /* CONSTANT_NameAndType */
1093 typedef struct forward_nameandtype {
1094 struct forward_nameandtype *next;
1098 } forward_nameandtype;
1100 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1101 typedef struct forward_fieldmethint {
1102 struct forward_fieldmethint *next;
1106 u2 nameandtype_index;
1107 } forward_fieldmethint;
1111 long int dumpsize = dump_size ();
1113 forward_class *forward_classes = NULL;
1114 forward_string *forward_strings = NULL;
1115 forward_nameandtype *forward_nameandtypes = NULL;
1116 forward_fieldmethint *forward_fieldmethints = NULL;
1118 /* number of entries in the constant_pool table */
1119 u4 cpcount = c -> cpcount = suck_u2();
1120 /* allocate memory */
1121 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1122 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1125 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1128 /* initialize constantpool */
1129 for (idx=0; idx<cpcount; idx++) {
1130 cptags[idx] = CONSTANT_UNUSED;
1131 cpinfos[idx] = NULL;
1135 /******* first pass *******/
1136 /* entries which cannot be resolved now are written into
1137 temporary structures and traversed again later */
1140 while (idx < cpcount) {
1141 /* get constant type */
1145 case CONSTANT_Class: {
1146 forward_class *nfc = DNEW(forward_class);
1148 nfc -> next = forward_classes;
1149 forward_classes = nfc;
1151 nfc -> thisindex = idx;
1152 /* reference to CONSTANT_NameAndType */
1153 nfc -> name_index = suck_u2 ();
1159 case CONSTANT_Fieldref:
1160 case CONSTANT_Methodref:
1161 case CONSTANT_InterfaceMethodref: {
1162 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1164 nff -> next = forward_fieldmethints;
1165 forward_fieldmethints = nff;
1167 nff -> thisindex = idx;
1170 /* class or interface type that contains the declaration of the field or method */
1171 nff -> class_index = suck_u2 ();
1172 /* name and descriptor of the field or method */
1173 nff -> nameandtype_index = suck_u2 ();
1179 case CONSTANT_String: {
1180 forward_string *nfs = DNEW (forward_string);
1182 nfs -> next = forward_strings;
1183 forward_strings = nfs;
1185 nfs -> thisindex = idx;
1186 /* reference to CONSTANT_Utf8_info with string characters */
1187 nfs -> string_index = suck_u2 ();
1193 case CONSTANT_NameAndType: {
1194 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1196 nfn -> next = forward_nameandtypes;
1197 forward_nameandtypes = nfn;
1199 nfn -> thisindex = idx;
1200 /* reference to CONSTANT_Utf8_info containing simple name */
1201 nfn -> name_index = suck_u2 ();
1202 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1203 nfn -> sig_index = suck_u2 ();
1209 case CONSTANT_Integer: {
1210 constant_integer *ci = NEW (constant_integer);
1213 count_const_pool_len += sizeof(constant_integer);
1216 ci -> value = suck_s4 ();
1217 cptags [idx] = CONSTANT_Integer;
1224 case CONSTANT_Float: {
1225 constant_float *cf = NEW (constant_float);
1228 count_const_pool_len += sizeof(constant_float);
1231 cf -> value = suck_float ();
1232 cptags [idx] = CONSTANT_Float;
1238 case CONSTANT_Long: {
1239 constant_long *cl = NEW(constant_long);
1242 count_const_pool_len += sizeof(constant_long);
1245 cl -> value = suck_s8 ();
1246 cptags [idx] = CONSTANT_Long;
1252 case CONSTANT_Double: {
1253 constant_double *cd = NEW(constant_double);
1256 count_const_pool_len += sizeof(constant_double);
1259 cd -> value = suck_double ();
1260 cptags [idx] = CONSTANT_Double;
1266 case CONSTANT_Utf8: {
1268 /* number of bytes in the bytes array (not string-length) */
1269 u4 length = suck_u2();
1270 cptags [idx] = CONSTANT_Utf8;
1271 /* insert utf-string into the utf-symboltable */
1272 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1273 /* skip bytes of the string */
1274 skip_nbytes(length);
1280 sprintf (logtext, "Unkown constant type: %d",(int) t);
1289 /* resolve entries in temporary structures */
1291 while (forward_classes) {
1293 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1295 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1296 /* retrieve class from class-table */
1297 cpinfos [forward_classes -> thisindex] = class_new (name);
1299 forward_classes = forward_classes -> next;
1303 while (forward_strings) {
1305 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1307 log_text("forward_string:");
1308 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1310 log_text("\n------------------"); */
1311 /* resolve utf-string */
1312 cptags [forward_strings -> thisindex] = CONSTANT_String;
1313 cpinfos [forward_strings -> thisindex] = text;
1315 forward_strings = forward_strings -> next;
1318 while (forward_nameandtypes) {
1319 constant_nameandtype *cn = NEW (constant_nameandtype);
1322 count_const_pool_len += sizeof(constant_nameandtype);
1325 /* resolve simple name and descriptor */
1326 cn -> name = class_getconstant
1327 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1328 cn -> descriptor = class_getconstant
1329 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1331 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1332 cpinfos [forward_nameandtypes -> thisindex] = cn;
1334 forward_nameandtypes = forward_nameandtypes -> next;
1338 while (forward_fieldmethints) {
1339 constant_nameandtype *nat;
1340 constant_FMIref *fmi = NEW (constant_FMIref);
1343 count_const_pool_len += sizeof(constant_FMIref);
1345 /* resolve simple name and descriptor */
1346 nat = class_getconstant
1347 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1350 log_text("trying to resolve:");
1351 log_text(nat->name->text);
1352 switch(forward_fieldmethints ->tag) {
1353 case CONSTANT_Fieldref:
1354 log_text("CONSTANT_Fieldref");
1356 case CONSTANT_InterfaceMethodref:
1357 log_text("CONSTANT_InterfaceMethodref");
1359 case CONSTANT_Methodref:
1360 log_text("CONSTANT_Methodref");
1364 fmi -> class = class_getconstant
1365 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1366 fmi -> name = nat -> name;
1367 fmi -> descriptor = nat -> descriptor;
1369 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1370 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1372 switch (forward_fieldmethints -> tag) {
1373 case CONSTANT_Fieldref: /* check validity of descriptor */
1374 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1376 case CONSTANT_InterfaceMethodref:
1377 case CONSTANT_Methodref: /* check validity of descriptor */
1378 checkmethoddescriptor (fmi->descriptor);
1382 forward_fieldmethints = forward_fieldmethints -> next;
1386 /* class_showconstantpool(c); */
1388 dump_release (dumpsize);
1392 /********************** Function: class_load ***********************************
1394 Loads everything interesting about a class from the class file. The
1395 'classinfo' structure must have been allocated previously.
1397 The super class and the interfaces implemented by this class need not be
1398 loaded. The link is set later by the function 'class_link'.
1400 The loaded class is removed from the list 'unloadedclasses' and added to
1401 the list 'unlinkedclasses'.
1403 *******************************************************************************/
1405 static int class_load (classinfo *c)
1411 count_class_loads++;
1414 /* output for debugging purposes */
1417 sprintf (logtext, "Loading class: ");
1418 utf_sprint (logtext+strlen(logtext), c->name );
1422 /* load classdata, throw exception on error */
1424 if (!suck_start (c->name)) {
1425 throw_classnotfoundexception2(c->name);
1429 /* check signature */
1430 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1434 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1435 sprintf (logtext, "File version %d.%d is not supported",
1436 (int) ma, (int) mi);
1440 class_loadcpool (c);
1442 c->erroneous_state=0;
1443 c->initializing_thread=0;
1445 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1446 c -> impldBy = NULL;
1449 c -> flags = suck_u2 ();
1453 /* retrieve superclass */
1454 if ( (i = suck_u2 () ) ) {
1455 c -> super = class_getconstant (c, i, CONSTANT_Class);
1461 /* retrieve interfaces */
1462 c -> interfacescount = suck_u2 ();
1463 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1464 for (i=0; i < c -> interfacescount; i++) {
1465 c -> interfaces [i] =
1466 class_getconstant (c, suck_u2(), CONSTANT_Class);
1470 c -> fieldscount = suck_u2 ();
1471 /* utf_display(c->name);
1472 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1474 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1475 for (i=0; i < c -> fieldscount; i++) {
1476 field_load (&(c->fields[i]), c);
1480 c -> methodscount = suck_u2 ();
1481 c -> methods = MNEW (methodinfo, c -> methodscount);
1482 for (i=0; i < c -> methodscount; i++) {
1483 method_load (&(c -> methods [i]), c);
1487 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1488 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1489 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1492 /* load variable-length attribute structures */
1493 attribute_load (suck_u2(), c);
1498 /* remove class from list of unloaded classes and
1499 add to list of unlinked classes */
1500 list_remove (&unloadedclasses, c);
1501 list_addlast (&unlinkedclasses, c);
1508 /************** internal Function: class_highestinterface ***********************
1510 Used by the function class_link to determine the amount of memory needed
1511 for the interface table.
1513 *******************************************************************************/
1515 static s4 class_highestinterface (classinfo *c)
1520 if ( ! (c->flags & ACC_INTERFACE) ) {
1521 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1522 utf_sprint (logtext+strlen(logtext), c->name);
1527 for (i=0; i<c->interfacescount; i++) {
1528 s4 h2 = class_highestinterface (c->interfaces[i]);
1535 /* class_addinterface **********************************************************
1537 Is needed by class_link for adding a VTBL to a class. All interfaces
1538 implemented by ic are added as well.
1540 *******************************************************************************/
1542 static void class_addinterface (classinfo *c, classinfo *ic)
1546 vftbl *vftbl = c->vftbl;
1548 if (i >= vftbl->interfacetablelength)
1549 panic ("Inernal error: interfacetable overflow");
1550 if (vftbl->interfacetable[-i])
1553 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1554 vftbl->interfacevftbllength[i] = 1;
1555 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1556 vftbl->interfacetable[-i][0] = NULL;
1559 vftbl->interfacevftbllength[i] = ic->methodscount;
1560 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1563 count_vftbl_len += sizeof(methodptr) *
1564 (ic->methodscount + (ic->methodscount == 0));
1567 for (j=0; j<ic->methodscount; j++) {
1570 for (m = 0; m < sc->methodscount; m++) {
1571 methodinfo *mi = &(sc->methods[m]);
1572 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1573 vftbl->interfacetable[-i][j] =
1574 vftbl->table[mi->vftblindex];
1584 for (j = 0; j < ic->interfacescount; j++)
1585 class_addinterface(c, ic->interfaces[j]);
1589 /******************* Function: class_new_array *********************************
1591 This function is called by class_new to setup an array class.
1593 *******************************************************************************/
1596 class_new_array(classinfo *c)
1598 classinfo *comp = NULL;
1602 /* Array classes are not loaded from classfiles. */
1603 list_remove (&unloadedclasses, c);
1605 /* Check array class name */
1606 namelen = c->name->blength;
1607 if (namelen < 2 || c->name->text[0] != '[')
1608 panic("Invalid array class name.");
1610 /* Check the component type */
1611 switch (c->name->text[1]) {
1613 /* c is an array of arrays. We have to create the component class. */
1614 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1618 /* c is an array of objects. */
1619 if (namelen < 4 || c->name->text[namelen-1] != ';')
1620 panic("Invalid array class name.");
1621 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1625 /* Setup the array class */
1626 c->super = class_java_lang_Object;
1628 c->interfacescount = 2;
1629 c->interfaces = MNEW(classinfo*,2);
1630 c->interfaces[0] = class_java_lang_Cloneable;
1631 c->interfaces[1] = class_java_io_Serializable;
1633 c->methodscount = 1;
1634 c->methods = MNEW (methodinfo, c->methodscount);
1637 memset(clone,0,sizeof(methodinfo));
1638 clone->flags = ACC_PUBLIC; /* XXX protected? */
1639 clone->name = utf_new_char("clone");
1640 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1642 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1643 clone->monoPoly = MONO; /* XXX should be poly? */
1645 /* XXX: field: length? */
1647 /* The array class has to be linked */
1648 list_addlast(&unlinkedclasses,c);
1651 * Array classes which are created after the other classes have been
1652 * 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;
1715 desc->elementvftbl = compvftbl;
1716 desc->dimension = 1;
1720 /* c is an array of a primitive type */
1721 switch (c->name->text[1]) {
1722 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1723 desc->dataoffset = OFFSET(java_booleanarray,data);
1724 desc->componentsize = sizeof(u1); break;
1725 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1726 desc->dataoffset = OFFSET(java_bytearray,data);
1727 desc->componentsize = sizeof(u1); break;
1728 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1729 desc->dataoffset = OFFSET(java_chararray,data);
1730 desc->componentsize = sizeof(u2); break;
1731 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1732 desc->dataoffset = OFFSET(java_doublearray,data);
1733 desc->componentsize = sizeof(double); break;
1734 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1735 desc->dataoffset = OFFSET(java_floatarray,data);
1736 desc->componentsize = sizeof(float); break;
1737 case 'I': desc->arraytype = ARRAYTYPE_INT;
1738 desc->dataoffset = OFFSET(java_intarray,data);
1739 desc->componentsize = sizeof(s4); break;
1740 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1741 desc->dataoffset = OFFSET(java_longarray,data);
1742 desc->componentsize = sizeof(s8); break;
1743 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1744 desc->dataoffset = OFFSET(java_shortarray,data);
1745 desc->componentsize = sizeof(s2); break;
1747 panic("Invalid array class name");
1750 desc->componentvftbl = NULL;
1751 desc->elementvftbl = NULL;
1752 desc->dimension = 1;
1758 /********************** Function: class_link ***********************************
1760 Tries to link a class. The super class and every implemented interface must
1761 already have been linked. The function calculates the length in bytes that
1762 an instance of this class requires as well as the VTBL for methods and
1765 If the class can be linked, it is removed from the list 'unlinkedclasses'
1766 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1769 Attention: If cyclical class definitions are encountered, the program gets
1770 into an infinite loop (we'll have to work that out)
1772 *******************************************************************************/
1774 void class_link(classinfo *c)
1776 s4 supervftbllength; /* vftbllegnth of super class */
1777 s4 vftbllength; /* vftbllength of current class */
1778 s4 interfacetablelength; /* interface table length */
1779 classinfo *super = c->super; /* super class */
1780 classinfo *ic, *c2; /* intermediate class variables */
1781 vftbl *v; /* vftbl of current class */
1782 s4 i; /* interface/method/field counter */
1783 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1786 /* check if all superclasses are already linked, if not put c at end of
1787 unlinked list and return. Additionally initialize class fields. */
1789 /* check interfaces */
1791 for (i = 0; i < c->interfacescount; i++) {
1792 ic = c->interfaces[i];
1794 list_remove(&unlinkedclasses, c);
1795 list_addlast(&unlinkedclasses, c);
1800 /* check super class */
1802 if (super == NULL) { /* class java.long.Object */
1804 c->classUsed = USED; /* Object class is always used CO-RT*/
1805 c -> impldBy = NULL;
1806 c->instancesize = sizeof(java_objectheader);
1808 vftbllength = supervftbllength = 0;
1810 c->finalizer = NULL;
1813 if (!super->linked) {
1814 list_remove(&unlinkedclasses, c);
1815 list_addlast(&unlinkedclasses, c);
1819 /* handle array classes */
1820 if (c->name->text[0] == '[')
1821 if ((arraydesc = class_link_array(c)) == NULL) {
1822 list_remove(&unlinkedclasses, c);
1823 list_addlast(&unlinkedclasses, c);
1827 if (c->flags & ACC_INTERFACE)
1828 c->index = interfaceindex++;
1830 c->index = super->index + 1;
1832 c->instancesize = super->instancesize;
1834 vftbllength = supervftbllength = super->vftbl->vftbllength;
1836 c->finalizer = super->finalizer;
1841 sprintf (logtext, "Linking Class: ");
1842 utf_sprint (logtext+strlen(logtext), c->name );
1846 /* compute vftbl length */
1848 for (i = 0; i < c->methodscount; i++) {
1849 methodinfo *m = &(c->methods[i]);
1851 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1852 classinfo *sc = super;
1855 for (j = 0; j < sc->methodscount; j++) {
1856 if (method_canoverwrite(m, &(sc->methods[j]))) {
1857 m->vftblindex = sc->methods[j].vftblindex;
1858 goto foundvftblindex;
1863 m->vftblindex = (vftbllength++);
1869 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1872 /* compute interfacetable length */
1874 interfacetablelength = 0;
1877 for (i = 0; i < c2->interfacescount; i++) {
1878 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1879 if (h > interfacetablelength)
1880 interfacetablelength = h;
1885 /* allocate virtual function table */
1887 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1888 (vftbllength - 1) + sizeof(methodptr*) *
1889 (interfacetablelength - (interfacetablelength > 0)));
1890 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1891 (interfacetablelength > 1));
1892 c->header.vftbl = c->vftbl = v;
1894 v->vftbllength = vftbllength;
1895 v->interfacetablelength = interfacetablelength;
1896 v->arraydesc = arraydesc;
1898 /* store interface index in vftbl */
1899 if (c->flags & ACC_INTERFACE)
1900 v->baseval = -(c->index);
1902 /* copy virtual function table of super class */
1904 for (i = 0; i < supervftbllength; i++)
1905 v->table[i] = super->vftbl->table[i];
1907 /* add method stubs into virtual function table */
1909 for (i = 0; i < c->methodscount; i++) {
1910 methodinfo *m = &(c->methods[i]);
1911 if (!(m->flags & ACC_STATIC)) {
1912 v->table[m->vftblindex] = m->stubroutine;
1916 /* compute instance size and offset of each field */
1918 for (i = 0; i < c->fieldscount; i++) {
1920 fieldinfo *f = &(c->fields[i]);
1922 if (!(f->flags & ACC_STATIC) ) {
1923 dsize = desc_typesize (f->descriptor);
1924 c->instancesize = ALIGN (c->instancesize, dsize);
1925 f->offset = c->instancesize;
1926 c->instancesize += dsize;
1930 /* initialize interfacetable and interfacevftbllength */
1932 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1935 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1938 for (i = 0; i < interfacetablelength; i++) {
1939 v->interfacevftbllength[i] = 0;
1940 v->interfacetable[-i] = NULL;
1943 /* add interfaces */
1945 for (c2 = c; c2 != NULL; c2 = c2->super)
1946 for (i = 0; i < c2->interfacescount; i++) {
1947 class_addinterface (c, c2->interfaces[i]);
1950 /* add finalizer method (not for java.lang.Object) */
1952 if (super != NULL) {
1954 static utf *finame = NULL;
1955 static utf *fidesc = NULL;
1958 finame = utf_finalize;
1960 fidesc = utf_fidesc;
1962 fi = class_findmethod (c, finame, fidesc);
1964 if (!(fi->flags & ACC_STATIC)) {
1974 list_remove (&unlinkedclasses, c);
1975 list_addlast (&linkedclasses, c);
1980 /******************* Function: class_freepool **********************************
1982 Frees all resources used by this classes Constant Pool.
1984 *******************************************************************************/
1986 static void class_freecpool (classinfo *c)
1992 for (idx=0; idx < c->cpcount; idx++) {
1993 tag = c->cptags[idx];
1994 info = c->cpinfos[idx];
1998 case CONSTANT_Fieldref:
1999 case CONSTANT_Methodref:
2000 case CONSTANT_InterfaceMethodref:
2001 FREE (info, constant_FMIref);
2003 case CONSTANT_Integer:
2004 FREE (info, constant_integer);
2006 case CONSTANT_Float:
2007 FREE (info, constant_float);
2010 FREE (info, constant_long);
2012 case CONSTANT_Double:
2013 FREE (info, constant_double);
2015 case CONSTANT_NameAndType:
2016 FREE (info, constant_nameandtype);
2022 MFREE (c -> cptags, u1, c -> cpcount);
2023 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2027 /*********************** Function: class_free **********************************
2029 Frees all resources used by the class.
2031 *******************************************************************************/
2033 static void class_free (classinfo *c)
2038 class_freecpool (c);
2040 MFREE (c->interfaces, classinfo*, c->interfacescount);
2042 for (i = 0; i < c->fieldscount; i++)
2043 field_free(&(c->fields[i]));
2045 for (i = 0; i < c->methodscount; i++)
2046 method_free(&(c->methods[i]));
2047 MFREE (c->methods, methodinfo, c->methodscount);
2049 if ((v = c->vftbl) != NULL) {
2051 mem_free(v->arraydesc,sizeof(arraydescriptor));
2053 for (i = 0; i < v->interfacetablelength; i++) {
2054 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2056 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2058 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2059 sizeof(methodptr*) * (v->interfacetablelength -
2060 (v->interfacetablelength > 0));
2061 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2062 (v->interfacetablelength > 1));
2066 if (c->innerclasscount)
2067 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2069 /* if (c->classvftbl)
2070 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2072 FREE (c, classinfo);
2075 /************************* Function: class_findfield ***************************
2077 Searches a 'classinfo' structure for a field having the given name and
2080 *******************************************************************************/
2083 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2088 for (i = 0; i < c->fieldscount; i++) {
2089 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2090 return &(c->fields[i]);
2093 panic ("Can not find field given in CONSTANT_Fieldref");
2098 /************************* Function: class_findmethod **************************
2100 Searches a 'classinfo' structure for a method having the given name and
2101 type and returns the index in the class info structure.
2102 If type is NULL, it is ignored.
2104 *******************************************************************************/
2106 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2109 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2111 int buffer_len, pos;
2113 #ifdef JOWENN_DEBUG1
2116 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2118 buffer = MNEW(char, buffer_len);
2120 strcpy(buffer, "class_findmethod: method:");
2121 utf_sprint(buffer+strlen(buffer), name);
2122 strcpy(buffer+strlen(buffer), ", desc: ");
2123 utf_sprint(buffer+strlen(buffer), desc);
2124 strcpy(buffer+strlen(buffer), ", classname: ");
2125 utf_sprint(buffer+strlen(buffer), c->name);
2129 MFREE(buffer, char, buffer_len);
2131 for (i = 0; i < c->methodscount; i++) {
2132 #ifdef JOWENN_DEBUG2
2134 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2136 buffer = MNEW(char, buffer_len);
2138 strcpy(buffer, "class_findmethod: comparing to method:");
2139 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2140 strcpy(buffer+strlen(buffer), ", desc: ");
2141 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2145 MFREE(buffer, char, buffer_len);
2149 if ((c->methods[i].name == name) && ((desc == NULL) ||
2150 (c->methods[i].descriptor == desc)))
2153 #ifdef JOWENN_DEBUG2
2154 class_showconstantpool(c);
2155 log_text("class_findmethod: returning NULL");
2162 /************************* Function: class_findmethod **************************
2164 Searches a 'classinfo' structure for a method having the given name and
2166 If type is NULL, it is ignored.
2168 *******************************************************************************/
2170 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2174 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2176 int buffer_len, pos;
2178 #ifdef JOWENN_DEBUG1
2181 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2183 buffer = MNEW(char, buffer_len);
2185 strcpy(buffer, "class_findmethod: method:");
2186 utf_sprint(buffer+strlen(buffer), name);
2187 strcpy(buffer+strlen(buffer), ", desc: ");
2188 utf_sprint(buffer+strlen(buffer), desc);
2189 strcpy(buffer+strlen(buffer), ", classname: ");
2190 utf_sprint(buffer+strlen(buffer), c->name);
2194 MFREE(buffer, char, buffer_len);
2196 for (i = 0; i < c->methodscount; i++) {
2197 #ifdef JOWENN_DEBUG2
2199 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2201 buffer = MNEW(char, buffer_len);
2203 strcpy(buffer, "class_findmethod: comparing to method:");
2204 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2205 strcpy(buffer+strlen(buffer), ", desc: ");
2206 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2210 MFREE(buffer, char, buffer_len);
2214 if ((c->methods[i].name == name) && ((desc == NULL) ||
2215 (c->methods[i].descriptor == desc)))
2216 return &(c->methods[i]);
2218 #ifdef JOWENN_DEBUG2
2219 class_showconstantpool(c);
2220 log_text("class_findmethod: returning NULL");
2224 s4 idx=class_findmethodIndex(c,name,desc);
2225 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2226 if (idx==-1) return NULL;
2227 return &(c->methods[idx]);
2235 /************************* Function: class_findmethod_approx ******************
2237 like class_findmethod but ignores the return value when comparing the
2240 *******************************************************************************/
2242 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2246 for (i = 0; i < c->methodscount; i++)
2247 if (c->methods[i].name == name) {
2248 utf *meth_descr = c->methods[i].descriptor;
2252 return &(c->methods[i]);
2254 if (desc->blength <= meth_descr->blength) {
2255 /* current position in utf text */
2256 char *desc_utf_ptr = desc->text;
2257 char *meth_utf_ptr = meth_descr->text;
2258 /* points behind utf strings */
2259 char *desc_end = utf_end(desc);
2260 char *meth_end = utf_end(meth_descr);
2263 /* compare argument types */
2264 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2266 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2267 break; /* no match */
2270 return &(c->methods[i]); /* all parameter types equal */
2278 /***************** Function: class_resolvemethod_approx ***********************
2280 Searches a class and every super class for a method (without paying
2281 attention to the return value)
2283 *******************************************************************************/
2285 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2288 /* search for method (ignore returntype) */
2289 methodinfo *m = class_findmethod_approx (c, name, desc);
2292 /* search superclass */
2299 /************************* Function: class_resolvemethod ***********************
2301 Searches a class and every super class for a method.
2303 *******************************************************************************/
2305 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2308 methodinfo *m = class_findmethod(c, name, desc);
2310 /* search superclass */
2318 /************************* Function: class_issubclass **************************
2320 Checks if sub is a descendant of super.
2322 *******************************************************************************/
2324 bool class_issubclass(classinfo *sub, classinfo *super)
2327 if (!sub) return false;
2328 if (sub==super) return true;
2335 /****************** Initialization function for classes ******************
2337 In Java, every class can have a static initialization function. This
2338 function has to be called BEFORE calling other methods or accessing static
2341 *******************************************************************************/
2344 extern int blockInts;
2347 void class_init(classinfo *c)
2350 java_objectheader *exceptionptr;
2355 if (!makeinitializations)
2359 c -> initialized = true;
2364 count_class_inits++;
2368 class_init (c->super);
2369 for (i=0; i < c->interfacescount; i++)
2370 class_init(c->interfaces[i]); /* real */
2372 m = class_findmethod (c, utf_clinit, utf_fidesc);
2375 sprintf (logtext, "Class ");
2376 utf_sprint (logtext+strlen(logtext), c->name);
2377 sprintf (logtext+strlen(logtext), " has no initializer");
2380 /* goto callinitialize;*/
2384 if (! (m->flags & ACC_STATIC))
2385 panic ("Class initializer is not static!");
2388 sprintf (logtext, "Starting initializer for class: ");
2389 utf_sprint (logtext+strlen(logtext), c->name);
2398 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2401 assert(blockInts == 0);
2406 printf ("#### Initializer of ");
2407 utf_display (c->name);
2408 printf (" has thrown: ");
2409 utf_display (exceptionptr->vftbl->class->name);
2415 sprintf (logtext, "Finished initializer for class: ");
2416 utf_sprint (logtext+strlen(logtext), c->name);
2419 if (c->name == utf_systemclass) {
2420 /* class java.lang.System requires explicit initialization */
2423 printf ("#### Initializing class System");
2425 /* find initializing method */
2426 m = class_findmethod (c,
2427 utf_initsystemclass,
2431 /* no method found */
2432 /* printf("initializeSystemClass failed"); */
2440 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2443 assert(blockInts == 0);
2448 printf ("#### initializeSystemClass has thrown: ");
2449 utf_display (exceptionptr->vftbl->class->name);
2460 /********* Function: find_class_method_constant *********/
2461 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2466 for (i=0; i<c->cpcount; i++) {
2468 e = c -> cpinfos [i];
2471 switch (c -> cptags [i]) {
2472 case CONSTANT_Methodref:
2474 constant_FMIref *fmi = e;
2475 if ( (fmi->class->name == c1)
2476 && (fmi->name == m1)
2477 && (fmi->descriptor == d1)) {
2484 case CONSTANT_InterfaceMethodref:
2486 constant_FMIref *fmi = e;
2487 if ( (fmi->class->name == c1)
2488 && (fmi->name == m1)
2489 && (fmi->descriptor == d1)) {
2503 void class_showconstanti(classinfo *c, int ii)
2509 printf ("#%d: ", (int) i);
2511 switch (c->cptags [i]) {
2512 case CONSTANT_Class:
2513 printf("Classreference -> ");
2514 utf_display(((classinfo*)e)->name);
2517 case CONSTANT_Fieldref:
2518 printf("Fieldref -> "); goto displayFMIi;
2519 case CONSTANT_Methodref:
2520 printf("Methodref -> "); goto displayFMIi;
2521 case CONSTANT_InterfaceMethodref:
2522 printf("InterfaceMethod -> "); goto displayFMIi;
2525 constant_FMIref *fmi = e;
2526 utf_display(fmi->class->name);
2528 utf_display(fmi->name);
2530 utf_display(fmi->descriptor);
2534 case CONSTANT_String:
2535 printf("String -> ");
2538 case CONSTANT_Integer:
2539 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2541 case CONSTANT_Float:
2542 printf("Float -> %f", ((constant_float*)e)->value);
2544 case CONSTANT_Double:
2545 printf("Double -> %f", ((constant_double*)e)->value);
2549 u8 v = ((constant_long*)e)->value;
2551 printf("Long -> %ld", (long int) v);
2553 printf("Long -> HI: %ld, LO: %ld\n",
2554 (long int) v.high, (long int) v.low);
2558 case CONSTANT_NameAndType:
2560 constant_nameandtype *cnt = e;
2561 printf("NameAndType: ");
2562 utf_display(cnt->name);
2564 utf_display(cnt->descriptor);
2572 panic("Invalid type of ConstantPool-Entry");
2579 void class_showconstantpool (classinfo *c)
2584 printf ("---- dump of constant pool ----\n");
2586 for (i=0; i<c->cpcount; i++) {
2587 printf ("#%d: ", (int) i);
2589 e = c -> cpinfos [i];
2592 switch (c -> cptags [i]) {
2593 case CONSTANT_Class:
2594 printf ("Classreference -> ");
2595 utf_display ( ((classinfo*)e) -> name );
2598 case CONSTANT_Fieldref:
2599 printf ("Fieldref -> "); goto displayFMI;
2600 case CONSTANT_Methodref:
2601 printf ("Methodref -> "); goto displayFMI;
2602 case CONSTANT_InterfaceMethodref:
2603 printf ("InterfaceMethod -> "); goto displayFMI;
2606 constant_FMIref *fmi = e;
2607 utf_display ( fmi->class->name );
2609 utf_display ( fmi->name);
2611 utf_display ( fmi->descriptor );
2615 case CONSTANT_String:
2616 printf ("String -> ");
2619 case CONSTANT_Integer:
2620 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2622 case CONSTANT_Float:
2623 printf ("Float -> %f", ((constant_float*)e) -> value);
2625 case CONSTANT_Double:
2626 printf ("Double -> %f", ((constant_double*)e) -> value);
2630 u8 v = ((constant_long*)e) -> value;
2632 printf ("Long -> %ld", (long int) v);
2634 printf ("Long -> HI: %ld, LO: %ld\n",
2635 (long int) v.high, (long int) v.low);
2639 case CONSTANT_NameAndType:
2641 constant_nameandtype *cnt = e;
2642 printf ("NameAndType: ");
2643 utf_display (cnt->name);
2645 utf_display (cnt->descriptor);
2649 printf ("Utf8 -> ");
2653 panic ("Invalid type of ConstantPool-Entry");
2663 /********** Function: class_showmethods (debugging only) *************/
2665 void class_showmethods (classinfo *c)
2669 printf ("--------- Fields and Methods ----------------\n");
2670 printf ("Flags: "); printflags (c->flags); printf ("\n");
2672 printf ("This: "); utf_display (c->name); printf ("\n");
2674 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2676 printf ("Index: %d\n", c->index);
2678 printf ("interfaces:\n");
2679 for (i=0; i < c-> interfacescount; i++) {
2681 utf_display (c -> interfaces[i] -> name);
2682 printf (" (%d)\n", c->interfaces[i] -> index);
2685 printf ("fields:\n");
2686 for (i=0; i < c -> fieldscount; i++) {
2687 field_display (&(c -> fields[i]));
2690 printf ("methods:\n");
2691 for (i=0; i < c -> methodscount; i++) {
2692 methodinfo *m = &(c->methods[i]);
2693 if ( !(m->flags & ACC_STATIC))
2694 printf ("vftblindex: %d ", m->vftblindex);
2696 method_display ( m );
2700 printf ("Virtual function table:\n");
2701 for (i=0; i<c->vftbl->vftbllength; i++) {
2702 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2709 /******************************************************************************/
2710 /******************* General functions for the class loader *******************/
2711 /******************************************************************************/
2713 /********************* Function: loader_load ***********************************
2715 Loads and links the class desired class and each class and interface
2717 Returns: a pointer to this class
2719 *******************************************************************************/
2721 static int loader_load_running = 0;
2723 classinfo *loader_load (utf *topname)
2727 long int starttime=0,stoptime=0;
2729 /* avoid recursive calls */
2730 if (loader_load_running)
2731 return class_new(topname);
2732 loader_load_running++;
2734 intsDisable(); /* schani */
2737 starttime = getcputime();
2739 top = class_new (topname);
2742 while ( (c = list_first(&unloadedclasses)) ) {
2743 if (!class_load (c)) {
2744 list_remove (&unloadedclasses, c);
2750 while ( (c = list_first(&unlinkedclasses)) ) {
2755 loader_compute_subclasses();
2758 if (getloadingtime) {
2759 stoptime = getcputime();
2760 loadingtime += (stoptime-starttime);
2763 intsRestore(); /* schani */
2765 loader_load_running--;
2771 /**************** function: create_primitive_classes ***************************
2773 create classes representing primitive types
2775 ********************************************************************************/
2778 void create_primitive_classes()
2782 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2783 /* create primitive class */
2784 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2785 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2786 c -> impldBy = NULL;
2788 /* prevent loader from loading primitive class */
2789 list_remove (&unloadedclasses, c);
2790 /* add to unlinked classes */
2791 list_addlast (&unlinkedclasses, c);
2792 c -> super = class_java_lang_Object;
2795 primitivetype_table[i].class_primitive = c;
2797 /* create class for wrapping the primitive type */
2798 primitivetype_table[i].class_wrap =
2799 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2800 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2801 primitivetype_table[i].class_wrap -> impldBy = NULL;
2803 /* create the primitive array class */
2804 if (primitivetype_table[i].arrayname) {
2805 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2806 primitivetype_table[i].arrayclass = c;
2807 if (!c->linked) class_link(c);
2808 primitivetype_table[i].arrayvftbl = c->vftbl;
2813 /**************** function: class_primitive_from_sig ***************************
2815 return the primitive class indicated by the given signature character
2817 If the descriptor does not indicate a valid primitive type the
2818 return value is NULL.
2820 ********************************************************************************/
2822 classinfo *class_primitive_from_sig(char sig)
2825 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2826 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2827 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2828 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2829 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2830 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2831 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2832 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2833 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2838 /****************** function: class_from_descriptor ****************************
2840 return the class indicated by the given descriptor
2842 utf_ptr....first character of descriptor
2843 end_ptr....first character after the end of the string
2844 next.......if non-NULL, *next is set to the first character after
2846 mode.......what to do if a class descriptor is parsed successfully:
2847 CLASSLOAD_SKIP...skip it and return something != NULL
2848 CLASSLOAD_NEW....get classinfo * via class_new
2849 CLASSLOAD_LOAD...get classinfo * via loader_load
2851 If the descriptor is invalid the return value is NULL
2853 ********************************************************************************/
2855 classinfo *class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
2857 char *start = utf_ptr;
2861 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
2862 if (error) return NULL;
2863 if (next) *next = utf_ptr;
2871 if (mode == CLASSLOAD_SKIP) return class_java_lang_Object;
2872 name = utf_new(start,utf_ptr-start);
2873 return (mode == CLASSLOAD_LOAD) ? loader_load(name) : class_new(name);
2875 return class_primitive_from_sig(*start);
2879 /*************** function: create_pseudo_classes *******************************
2881 create pseudo classes used by the typechecker
2883 ********************************************************************************/
2886 create_pseudo_classes()
2888 /* pseudo class for Arraystubs (extends java.lang.Object) */
2890 pseudo_class_Arraystub = class_new( utf_new_char(";Arraystub;") );
2891 list_remove(&unloadedclasses,pseudo_class_Arraystub);
2893 pseudo_class_Arraystub->super = class_java_lang_Object;
2894 pseudo_class_Arraystub->interfacescount = 2;
2895 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
2896 pseudo_class_Arraystub->interfaces[0] =
2897 class_java_lang_Cloneable;
2898 pseudo_class_Arraystub->interfaces[1] =
2899 class_java_io_Serializable;
2901 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
2902 class_link(pseudo_class_Arraystub);
2904 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
2906 /* pseudo class representing the null type */
2908 pseudo_class_Null = class_new( utf_new_char(";Null;") );
2909 list_remove(&unloadedclasses,pseudo_class_Null);
2911 pseudo_class_Null->super = class_java_lang_Object;
2913 list_addlast(&unlinkedclasses,pseudo_class_Null);
2914 class_link(pseudo_class_Null);
2917 /********************** Function: loader_init **********************************
2919 Initializes all lists and loads all classes required for the system or the
2922 *******************************************************************************/
2924 void loader_init (u1 * stackbottom)
2929 log_text("Entering loader_init");
2932 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2933 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2934 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2936 /* create utf-symbols for pointer comparison of frequently used strings */
2937 utf_innerclasses = utf_new_char("InnerClasses");
2938 utf_constantvalue = utf_new_char("ConstantValue");
2939 utf_code = utf_new_char("Code");
2940 utf_finalize = utf_new_char("finalize");
2941 utf_fidesc = utf_new_char("()V");
2942 utf_clinit = utf_new_char("<clinit>");
2943 utf_initsystemclass = utf_new_char("initializeSystemClass");
2944 utf_systemclass = utf_new_char("java/lang/System");
2945 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
2946 utf_initialize =utf_new_char("initialize");
2947 utf_initializedesc =utf_new_char("(I)V");
2949 utf_vmclass =utf_new_char("java/lang/VMClass");
2951 /* create some important classes */
2952 /* These classes have to be created now because the classinfo
2953 * pointers are used in the loading code.
2955 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
2956 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
2957 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
2958 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
2960 log_text("loader_init: java/lang/Object");
2961 /* load the classes which were created above */
2962 loader_load (class_java_lang_Object->name);
2964 loader_inited=1; /*JOWENN*/
2966 class_java_lang_Throwable =
2967 loader_load( utf_new_char("java/lang/Throwable") );
2969 log_text("loader_init: loader_load: java/lang/ClassCastException");
2970 class_java_lang_ClassCastException =
2971 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2972 class_java_lang_NullPointerException =
2973 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2974 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2975 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2976 class_java_lang_NegativeArraySizeException = loader_load (
2977 utf_new_char ("java/lang/NegativeArraySizeException") );
2978 class_java_lang_OutOfMemoryError = loader_load (
2979 utf_new_char ("java/lang/OutOfMemoryError") );
2980 class_java_lang_ArrayStoreException =
2981 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2982 class_java_lang_ArithmeticException =
2983 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2984 class_java_lang_ThreadDeath = /* schani */
2985 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2986 /* create classes representing primitive types */
2987 create_primitive_classes();
2989 /* create classes used by the typechecker */
2990 create_pseudo_classes();
2992 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2993 stringtable_update();
3001 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3002 proto_java_lang_ClassCastException =
3003 builtin_new(class_java_lang_ClassCastException);
3004 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3006 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3008 proto_java_lang_NullPointerException =
3009 builtin_new(class_java_lang_NullPointerException);
3010 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3011 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3013 proto_java_lang_ArrayIndexOutOfBoundsException =
3014 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3015 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3017 proto_java_lang_NegativeArraySizeException =
3018 builtin_new(class_java_lang_NegativeArraySizeException);
3019 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3021 proto_java_lang_OutOfMemoryError =
3022 builtin_new(class_java_lang_OutOfMemoryError);
3023 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3025 proto_java_lang_ArithmeticException =
3026 builtin_new(class_java_lang_ArithmeticException);
3027 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3029 proto_java_lang_ArrayStoreException =
3030 builtin_new(class_java_lang_ArrayStoreException);
3031 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3033 proto_java_lang_ThreadDeath = /* schani */
3034 builtin_new(class_java_lang_ThreadDeath);
3035 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3044 /********************* Function: loader_initclasses ****************************
3046 Initializes all loaded but uninitialized classes
3048 *******************************************************************************/
3050 void loader_initclasses ()
3054 intsDisable(); /* schani */
3056 if (makeinitializations) {
3057 c = list_first (&linkedclasses);
3060 c = list_next (&linkedclasses, c);
3064 intsRestore(); /* schani */
3067 static s4 classvalue;
3069 static void loader_compute_class_values (classinfo *c)
3073 c->vftbl->baseval = ++classvalue;
3076 while (subs != NULL) {
3077 loader_compute_class_values(subs);
3078 subs = subs->nextsub;
3080 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3085 for (i = 0; i < c->index; i++)
3087 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3088 utf_display(c->name);
3096 void loader_compute_subclasses ()
3100 intsDisable(); /* schani */
3102 c = list_first (&linkedclasses);
3104 if (!(c->flags & ACC_INTERFACE)) {
3108 c = list_next (&linkedclasses, c);
3111 c = list_first (&linkedclasses);
3113 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3114 c->nextsub = c->super->sub;
3117 c = list_next (&linkedclasses, c);
3120 loader_compute_class_values(class_java_lang_Object);
3122 intsRestore(); /* schani */
3127 /******************** function classloader_buffer ******************************
3129 sets buffer for reading classdata
3131 *******************************************************************************/
3133 void classload_buffer(u1 *buf, int len)
3136 classbuffer_size = len;
3137 classbuf_pos = buf - 1;
3141 /******************** Function: loader_close ***********************************
3145 *******************************************************************************/
3147 void loader_close ()
3151 while ( (c=list_first(&unloadedclasses)) ) {
3152 list_remove (&unloadedclasses,c);
3155 while ( (c=list_first(&unlinkedclasses)) ) {
3156 list_remove (&unlinkedclasses,c);
3159 while ( (c=list_first(&linkedclasses)) ) {
3160 list_remove (&linkedclasses,c);
3167 * These are local overrides for various environment variables in Emacs.
3168 * Please do not remove this and leave it at the end of the file, where
3169 * Emacs will automagically detect them.
3170 * ---------------------------------------------------------------------
3173 * indent-tabs-mode: t