1 /* loader.c - class loader functions
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
28 Changes: Andreas Krall
33 $Id: loader.c 719 2003-12-08 14:26:05Z edwin $
48 #include "toolbox/memory.h"
49 #include "toolbox/loging.h"
50 #include "threads/thread.h"
61 /* global variables ***********************************************************/
63 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
64 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
65 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
67 int count_class_infos = 0; /* variables for measurements */
68 int count_const_pool_len = 0;
69 int count_vftbl_len = 0;
70 int count_all_methods = 0;
71 int count_vmcode_len = 0;
72 int count_extable_len = 0;
73 int count_class_loads = 0;
74 int count_class_inits = 0;
76 bool loadverbose = false; /* switches for debug messages */
77 bool linkverbose = false;
78 bool initverbose = false;
80 bool makeinitializations = true;
82 bool getloadingtime = false; /* to measure the runtime */
83 long int loadingtime = 0;
85 static s4 interfaceindex; /* sequential numbering of interfaces */
87 list unloadedclasses; /* list of all referenced but not loaded classes */
88 list unlinkedclasses; /* list of all loaded but not linked classes */
89 list linkedclasses; /* list of all completely linked classes */
92 /* utf-symbols for pointer comparison of frequently used strings */
94 static utf *utf_innerclasses; /* InnerClasses */
95 static utf *utf_constantvalue; /* ConstantValue */
96 static utf *utf_code; /* Code */
97 static utf *utf_finalize; /* finalize */
98 static utf *utf_fidesc; /* ()V changed */
99 static utf *utf_clinit; /* <clinit> */
100 static utf *utf_initsystemclass; /* initializeSystemClass */
101 static utf *utf_systemclass; /* java/lang/System */
102 static utf *utf_vmclassloader; /*java/lang/VMClassLoader*/
103 static utf *utf_vmclass; /*java/lang/VMClassLoader*/
104 static utf *utf_initialize;
105 static utf *utf_initializedesc;
109 static unzFile uf = 0;
119 /* important system classes ***************************************************/
121 classinfo *class_java_lang_Object;
122 classinfo *class_java_lang_String;
124 classinfo *class_java_lang_Throwable;
125 classinfo *class_java_lang_Cloneable;
126 classinfo *class_java_io_Serializable;
128 /* Pseudo classes for the typechecker */
129 classinfo *pseudo_class_Arraystub = NULL;
130 classinfo *pseudo_class_Null = NULL;
131 classinfo *pseudo_class_New = NULL;
132 vftbl *pseudo_class_Arraystub_vftbl = NULL;
135 /* These are made static so they cannot be used for throwing in native */
137 static classinfo *class_java_lang_ClassCastException;
138 static classinfo *class_java_lang_NullPointerException;
139 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
140 static classinfo *class_java_lang_NegativeArraySizeException;
141 static classinfo *class_java_lang_OutOfMemoryError;
142 static classinfo *class_java_lang_ArithmeticException;
143 static classinfo *class_java_lang_ArrayStoreException;
144 static classinfo *class_java_lang_ThreadDeath;
146 static methodinfo method_clone_array;
148 static int loader_inited = 0;
150 /******************************************************************************
152 structure for primitive classes: contains the class for wrapping the
153 primitive type, the primitive class, the name of the class for wrapping,
154 the one character type signature and the name of the primitive class
156 ******************************************************************************/
158 /* CAUTION: Don't change the order of the types. This table is indexed
159 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
161 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
162 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
163 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
164 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
165 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
166 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
167 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
168 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
169 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
170 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }};
172 /* instances of important system classes **************************************/
174 java_objectheader *proto_java_lang_ClassCastException;
175 java_objectheader *proto_java_lang_NullPointerException;
176 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
177 java_objectheader *proto_java_lang_NegativeArraySizeException;
178 java_objectheader *proto_java_lang_OutOfMemoryError;
179 java_objectheader *proto_java_lang_ArithmeticException;
180 java_objectheader *proto_java_lang_ArrayStoreException;
181 java_objectheader *proto_java_lang_ThreadDeath;
183 /************* functions for reading classdata *********************************
185 getting classdata in blocks of variable size
186 (8,16,32,64-bit integer or float)
188 *******************************************************************************/
190 static char *classpath = ""; /* searchpath for classfiles */
191 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
192 static u1 *classbuf_pos; /* current position in classfile buffer */
193 static int classbuffer_size; /* size of classfile-data */
195 /* transfer block of classfile data into a buffer */
197 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
200 /* skip block of classfile data */
202 #define skip_nbytes(len) classbuf_pos+=len;
206 return *++classbuf_pos;
210 u1 a=suck_u1(), b=suck_u1();
211 return ((u2)a<<8)+(u2)b;
215 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
216 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
218 #define suck_s8() (s8) suck_u8()
219 #define suck_s2() (s2) suck_u2()
220 #define suck_s4() (s4) suck_u4()
221 #define suck_s1() (s1) suck_u1()
224 /* get u8 from classfile data */
231 return (hi << 32) + lo;
241 /* get float from classfile data */
242 static float suck_float()
249 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
250 memcpy((u1*) (&f), buffer, 4);
252 suck_nbytes((u1*) (&f), 4);
255 PANICIF (sizeof(float) != 4, "Incompatible float-format");
261 /* get double from classfile data */
262 static double suck_double()
269 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
270 memcpy((u1*) (&d), buffer, 8);
272 suck_nbytes((u1*) (&d), 8);
275 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
281 /************************** function suck_init *********************************
283 called once at startup, sets the searchpath for the classfiles
285 *******************************************************************************/
287 void suck_init(char *cpath)
294 /************************** function suck_start ********************************
296 returns true if classbuffer is already loaded or a file for the
297 specified class has succussfully been read in. All directories of
298 the searchpath are used to find the classfile (<classname>.class).
299 Returns false if no classfile is found and writes an error message.
301 *******************************************************************************/
303 bool suck_start(utf *classname)
306 #define MAXFILENAME 1000 /* maximum length of a filename */
308 char filename[MAXFILENAME+10]; /* room for '.class' */
309 char *pathpos; /* position in searchpath */
310 char c, *utf_ptr; /* pointer to the next utf8-character */
312 int filenamelen, err;
316 if (classbuffer) /* classbuffer is already valid */
323 /* skip path separator */
325 while (*pathpos == ':')
328 /* extract directory from searchpath */
331 while ((*pathpos) && (*pathpos != ':')) {
332 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
333 filename[filenamelen++] = *(pathpos++);
337 if (filenamelen > 4) {
338 if ( ((filename[filenamelen - 1] == 'p') || (filename[filenamelen - 1] == 'P')) &
339 ((filename[filenamelen - 2] == 'i') || (filename[filenamelen - 2] == 'I')) &
340 ((filename[filenamelen - 3] == 'z') || (filename[filenamelen - 3] == 'Z')) ) {
347 filename[filenamelen++] = '\0';
348 if (uf == 0) uf = unzOpen(filename);
350 utf_ptr = classname->text;
352 while (utf_ptr < utf_end(classname)) {
353 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
355 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
357 filename[filenamelen++] = c;
359 strcpy(filename + filenamelen, ".class");
360 if (cacao_locate(uf,classname) == UNZ_OK) {
361 unz_file_info file_info;
362 log_text("Class found in zip file");
363 if (unzGetCurrentFileInfo(uf, &file_info, filename,
364 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
365 if (unzOpenCurrentFile(uf) == UNZ_OK) {
366 classbuffer_size = file_info.uncompressed_size;
367 classbuffer = MNEW(u1, classbuffer_size);
368 classbuf_pos = classbuffer - 1;
369 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
370 if (unzReadCurrentFile(uf, classbuffer, classbuffer_size) == classbuffer_size) {
371 unzCloseCurrentFile(uf);
374 MFREE(classbuffer, u1, classbuffer_size);
375 log_text("Error while unzipping");
377 } else log_text("Error while opening file in archive");
378 } else log_text("Error while retrieving fileinfo");
380 unzCloseCurrentFile(uf);
385 filename[filenamelen++] = '/';
387 /* add classname to filename */
389 utf_ptr = classname->text;
390 while (utf_ptr < utf_end(classname)) {
391 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
393 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
395 filename[filenamelen++] = c;
400 strcpy(filename + filenamelen, ".class");
402 classfile = fopen(filename, "r");
403 if (classfile) { /* file exists */
405 /* determine size of classfile */
407 err = stat(filename, &buffer);
409 if (!err) { /* read classfile data */
410 classbuffer_size = buffer.st_size;
411 classbuffer = MNEW(u1, classbuffer_size);
412 classbuf_pos = classbuffer - 1;
413 fread(classbuffer, 1, classbuffer_size, classfile);
421 dolog("Warning: Can not open class file '%s'", filename);
428 /************************** function suck_stop *********************************
430 frees memory for buffer with classfile data.
431 Caution: this function may only be called if buffer has been allocated
432 by suck_start with reading a file
434 *******************************************************************************/
438 /* determine amount of classdata not retrieved by suck-operations */
440 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
442 if (classdata_left > 0) {
444 dolog("There are %d access bytes at end of classfile",
450 MFREE(classbuffer, u1, classbuffer_size);
455 /******************************************************************************/
456 /******************* Some support functions ***********************************/
457 /******************************************************************************/
461 void fprintflags (FILE *fp, u2 f)
463 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
464 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
465 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
466 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
467 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
468 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
469 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
470 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
471 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
472 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
473 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
476 /********** internal function: printflags (only for debugging) ***************/
477 void printflags (u2 f)
479 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
480 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
481 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
482 if ( f & ACC_STATIC ) printf (" STATIC");
483 if ( f & ACC_FINAL ) printf (" FINAL");
484 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
485 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
486 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
487 if ( f & ACC_NATIVE ) printf (" NATIVE");
488 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
489 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
493 /************************* Function: skipattribute *****************************
495 skips a (1) 'attribute' structure in the class file
497 *******************************************************************************/
499 static void skipattribute ()
502 skip_nbytes(suck_u4());
505 /********************** Function: skipattributebody ****************************
507 skips an attribute after the 16 bit reference to attribute_name has already
510 *******************************************************************************/
512 static void skipattributebody ()
514 skip_nbytes(suck_u4());
517 /************************* Function: skipattributes ****************************
519 skips num attribute structures
521 *******************************************************************************/
523 static void skipattributes (u4 num)
526 for (i = 0; i < num; i++)
530 /******************** function: innerclass_getconstant ************************
532 like class_getconstant, but if cptags is ZERO null is returned
534 *******************************************************************************/
536 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
538 /* invalid position in constantpool */
539 if (pos >= c->cpcount)
540 panic ("Attempt to access constant outside range");
542 /* constantpool entry of type 0 */
546 /* check type of constantpool entry */
547 if (c->cptags[pos] != ctype) {
548 error ("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
549 (int) ctype, (int) c->cptags[pos] );
552 return c->cpinfos[pos];
555 /************************ function: attribute_load ****************************
557 read attributes from classfile
559 *******************************************************************************/
561 static void attribute_load (u4 num, classinfo *c)
565 for (i = 0; i < num; i++) {
566 /* retrieve attribute name */
567 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
569 if ( aname == utf_innerclasses) {
570 /* innerclasses attribute */
572 /* skip attribute length */
574 /* number of records */
575 c->innerclasscount = suck_u2();
576 /* allocate memory for innerclass structure */
577 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
579 for (j=0;j<c->innerclasscount;j++) {
581 /* The innerclass structure contains a class with an encoded name,
582 its defining scope, its simple name and a bitmask of the access flags.
583 If an inner class is not a member, its outer_class is NULL,
584 if a class is anonymous, its name is NULL. */
586 innerclassinfo *info = c->innerclass + j;
588 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
589 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
590 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
591 info->flags = suck_u2 (); /* access_flags bitmask */
594 /* unknown attribute */
595 skipattributebody ();
600 /******************* function: checkfielddescriptor ****************************
602 checks whether a field-descriptor is valid and aborts otherwise
603 all referenced classes are inserted into the list of unloaded classes
605 *******************************************************************************/
607 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
609 char *tstart; /* pointer to start of classname */
611 char *start = utf_ptr;
613 switch (*utf_ptr++) {
627 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
628 panic ("Ill formed descriptor");
632 panic ("Ill formed descriptor");
635 /* exceeding characters */
636 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
640 /******************* function checkmethoddescriptor ****************************
642 checks whether a method-descriptor is valid and aborts otherwise.
643 All referenced classes are inserted into the list of unloaded classes.
645 *******************************************************************************/
647 static void checkmethoddescriptor (utf *d)
649 char *utf_ptr = d->text; /* current position in utf text */
650 char *end_pos = utf_end(d); /* points behind utf string */
651 char *tstart; /* pointer to start of classname */
655 /* method descriptor must start with parenthesis */
656 /* XXX check length */
657 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
659 /* XXX check length */
660 /* check arguments */
661 while ((c = *utf_ptr++) != ')') {
678 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
679 panic ("Ill formed method descriptor");
683 panic ("Ill formed methodtype-descriptor");
687 /* check returntype */
689 /* returntype void */
690 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
693 /* treat as field-descriptor */
694 checkfielddescriptor (utf_ptr,end_pos);
697 /***************** Function: print_arraydescriptor ****************************
699 Debugging helper for displaying an arraydescriptor
701 *******************************************************************************/
704 print_arraydescriptor(FILE *file,arraydescriptor *desc)
707 fprintf(file,"<NULL>");
712 if (desc->componentvftbl) {
713 if (desc->componentvftbl->class)
714 utf_fprint(file,desc->componentvftbl->class->name);
716 fprintf(file,"<no classinfo>");
722 if (desc->elementvftbl) {
723 if (desc->elementvftbl->class)
724 utf_fprint(file,desc->elementvftbl->class->name);
726 fprintf(file,"<no classinfo>");
730 fprintf(file,",%d,%d,%d,%d}",desc->arraytype,desc->dimension,
731 desc->dataoffset,desc->componentsize);
734 /******************************************************************************/
735 /************************** Functions for fields ****************************/
736 /******************************************************************************/
739 /************************ Function: field_load *********************************
741 Load everything about a class field from the class file and fill a
742 'fieldinfo' structure. For static fields, space in the data segment is
745 *******************************************************************************/
747 static void field_load (fieldinfo *f, classinfo *c)
752 f -> flags = suck_u2 (); /* ACC flags */
753 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
754 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
755 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
756 f -> offset = 0; /* offset from start of object */
760 case TYPE_INT: f->value.i = 0; break;
761 case TYPE_FLOAT: f->value.f = 0.0; break;
762 case TYPE_DOUBLE: f->value.d = 0.0; break;
763 case TYPE_ADDRESS: f->value.a = NULL;
764 heap_addreference (&(f->value.a)); /* make global reference (GC) */
768 f->value.l = 0; break;
770 f->value.l.low = 0; f->value.l.high = 0; break;
774 /* read attributes */
776 for (i=0; i<attrnum; i++) {
780 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
782 if ( aname != utf_constantvalue ) {
783 /* unknown attribute */
784 skipattributebody ();
787 /* constant value attribute */
789 /* skip attribute length */
791 /* index of value in constantpool */
794 /* initialize field with value from constantpool */
797 constant_integer *ci =
798 class_getconstant(c, pindex, CONSTANT_Integer);
799 f->value.i = ci -> value;
805 class_getconstant(c, pindex, CONSTANT_Long);
807 f->value.l = cl -> value;
813 class_getconstant(c, pindex, CONSTANT_Float);
815 f->value.f = cf->value;
820 constant_double *cd =
821 class_getconstant(c, pindex, CONSTANT_Double);
823 f->value.d = cd->value;
828 utf *u = class_getconstant(c, pindex, CONSTANT_String);
829 /* create javastring from compressed utf8-string */
830 f->value.a = literalstring_new(u);
835 log_text ("Invalid Constant - Type");
844 /********************** function: field_free **********************************/
846 static void field_free (fieldinfo *f)
852 /**************** Function: field_display (debugging only) ********************/
854 void field_display (fieldinfo *f)
857 printflags (f -> flags);
859 utf_display (f -> name);
861 utf_display (f -> descriptor);
862 printf (" offset: %ld\n", (long int) (f -> offset) );
866 /******************************************************************************/
867 /************************* Functions for methods ******************************/
868 /******************************************************************************/
871 /*********************** Function: method_load *********************************
873 Loads a method from the class file and fills an existing 'methodinfo'
874 structure. For native methods, the function pointer field is set to the
875 real function pointer, for JavaVM methods a pointer to the compiler is used
878 *******************************************************************************/
880 static void method_load (methodinfo *m, classinfo *c)
890 m -> flags = suck_u2 ();
891 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
892 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
893 checkmethoddescriptor(m->descriptor);
896 m -> exceptiontable = NULL;
897 m -> entrypoint = NULL;
899 m -> stubroutine = NULL;
900 m -> methodUsed = NOTUSED;
901 m -> monoPoly = MONO;
903 m -> subRedefsUsed = 0;
907 if (! (m->flags & ACC_NATIVE) ) {
908 m -> stubroutine = createcompilerstub (m);
912 functionptr f = native_findfunction
913 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
915 m -> stubroutine = createnativestub (f, m);
921 for (i=0; i<attrnum; i++) {
924 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
926 if ( aname != utf_code) {
927 skipattributebody ();
930 if (m -> jcode) panic ("Two code-attributes for one method!");
933 m -> maxstack = suck_u2();
934 m -> maxlocals = suck_u2();
935 m -> jcodelength = suck_u4();
936 m -> jcode = MNEW (u1, m->jcodelength);
937 suck_nbytes (m->jcode, m->jcodelength);
938 m -> exceptiontablelength = suck_u2 ();
939 m -> exceptiontable =
940 MNEW (exceptiontable, m->exceptiontablelength);
943 count_vmcode_len += m->jcodelength + 18;
944 count_extable_len += 8 * m->exceptiontablelength;
947 for (e=0; e < m->exceptiontablelength; e++) {
949 m -> exceptiontable[e].startpc = suck_u2();
950 m -> exceptiontable[e].endpc = suck_u2();
951 m -> exceptiontable[e].handlerpc = suck_u2();
954 if (!idx) m -> exceptiontable[e].catchtype = NULL;
956 m -> exceptiontable[e].catchtype =
957 class_getconstant (c, idx, CONSTANT_Class);
961 skipattributes ( suck_u2() );
968 /********************* Function: method_free ***********************************
970 frees all memory that was allocated for this method
972 *******************************************************************************/
974 static void method_free (methodinfo *m)
976 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
977 if (m->exceptiontable)
978 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
979 if (m->mcode) CFREE (m->mcode, m->mcodelength);
980 if (m->stubroutine) {
981 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
982 else removecompilerstub (m->stubroutine);
987 /************** Function: method_display (debugging only) **************/
989 void method_display (methodinfo *m)
992 printflags (m -> flags);
994 utf_display (m -> name);
996 utf_display (m -> descriptor);
1001 /******************** Function: method_canoverwrite ****************************
1003 Check if m and old are identical with respect to type and name. This means
1004 that old can be overwritten with m.
1006 *******************************************************************************/
1008 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1010 if (m->name != old->name) return false;
1011 if (m->descriptor != old->descriptor) return false;
1012 if (m->flags & ACC_STATIC) return false;
1019 /******************************************************************************/
1020 /************************ Functions for class *********************************/
1021 /******************************************************************************/
1024 /******************** function:: class_getconstant ******************************
1026 retrieves the value at position 'pos' of the constantpool of a class
1027 if the type of the value is other than 'ctype' the system is stopped
1029 *******************************************************************************/
1031 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1033 /* invalid position in constantpool */
1034 if (pos >= c->cpcount)
1035 panic ("Attempt to access constant outside range");
1037 /* check type of constantpool entry */
1039 if (c->cptags[pos] != ctype) {
1040 class_showconstantpool(c);
1041 error ("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1042 (int) ctype, (int) c->cptags[pos] );
1045 return c->cpinfos[pos];
1049 /********************* Function: class_constanttype ****************************
1051 Determines the type of a class entry in the ConstantPool
1053 *******************************************************************************/
1055 u4 class_constanttype (classinfo *c, u4 pos)
1057 if (pos >= c->cpcount)
1058 panic ("Attempt to access constant outside range");
1059 return c->cptags[pos];
1063 /******************** function: class_loadcpool ********************************
1065 loads the constantpool of a class,
1066 the entries are transformed into a simpler format
1067 by resolving references
1068 (a detailed overview of the compact structures can be found in global.h)
1070 *******************************************************************************/
1072 static void class_loadcpool (classinfo *c)
1075 /* The following structures are used to save information which cannot be
1076 processed during the first pass. After the complete constantpool has
1077 been traversed the references can be resolved.
1078 (only in specific order) */
1080 /* CONSTANT_Class_info entries */
1081 typedef struct forward_class {
1082 struct forward_class *next;
1087 /* CONSTANT_String */
1088 typedef struct forward_string {
1089 struct forward_string *next;
1094 /* CONSTANT_NameAndType */
1095 typedef struct forward_nameandtype {
1096 struct forward_nameandtype *next;
1100 } forward_nameandtype;
1102 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1103 typedef struct forward_fieldmethint {
1104 struct forward_fieldmethint *next;
1108 u2 nameandtype_index;
1109 } forward_fieldmethint;
1113 long int dumpsize = dump_size ();
1115 forward_class *forward_classes = NULL;
1116 forward_string *forward_strings = NULL;
1117 forward_nameandtype *forward_nameandtypes = NULL;
1118 forward_fieldmethint *forward_fieldmethints = NULL;
1120 /* number of entries in the constant_pool table */
1121 u4 cpcount = c -> cpcount = suck_u2();
1122 /* allocate memory */
1123 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1124 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1127 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1130 /* initialize constantpool */
1131 for (idx=0; idx<cpcount; idx++) {
1132 cptags[idx] = CONSTANT_UNUSED;
1133 cpinfos[idx] = NULL;
1137 /******* first pass *******/
1138 /* entries which cannot be resolved now are written into
1139 temporary structures and traversed again later */
1142 while (idx < cpcount) {
1143 /* get constant type */
1147 case CONSTANT_Class: {
1148 forward_class *nfc = DNEW(forward_class);
1150 nfc -> next = forward_classes;
1151 forward_classes = nfc;
1153 nfc -> thisindex = idx;
1154 /* reference to CONSTANT_NameAndType */
1155 nfc -> name_index = suck_u2 ();
1161 case CONSTANT_Fieldref:
1162 case CONSTANT_Methodref:
1163 case CONSTANT_InterfaceMethodref: {
1164 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1166 nff -> next = forward_fieldmethints;
1167 forward_fieldmethints = nff;
1169 nff -> thisindex = idx;
1172 /* class or interface type that contains the declaration of the field or method */
1173 nff -> class_index = suck_u2 ();
1174 /* name and descriptor of the field or method */
1175 nff -> nameandtype_index = suck_u2 ();
1181 case CONSTANT_String: {
1182 forward_string *nfs = DNEW (forward_string);
1184 nfs -> next = forward_strings;
1185 forward_strings = nfs;
1187 nfs -> thisindex = idx;
1188 /* reference to CONSTANT_Utf8_info with string characters */
1189 nfs -> string_index = suck_u2 ();
1195 case CONSTANT_NameAndType: {
1196 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1198 nfn -> next = forward_nameandtypes;
1199 forward_nameandtypes = nfn;
1201 nfn -> thisindex = idx;
1202 /* reference to CONSTANT_Utf8_info containing simple name */
1203 nfn -> name_index = suck_u2 ();
1204 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1205 nfn -> sig_index = suck_u2 ();
1211 case CONSTANT_Integer: {
1212 constant_integer *ci = NEW (constant_integer);
1215 count_const_pool_len += sizeof(constant_integer);
1218 ci -> value = suck_s4 ();
1219 cptags [idx] = CONSTANT_Integer;
1226 case CONSTANT_Float: {
1227 constant_float *cf = NEW (constant_float);
1230 count_const_pool_len += sizeof(constant_float);
1233 cf -> value = suck_float ();
1234 cptags [idx] = CONSTANT_Float;
1240 case CONSTANT_Long: {
1241 constant_long *cl = NEW(constant_long);
1244 count_const_pool_len += sizeof(constant_long);
1247 cl -> value = suck_s8 ();
1248 cptags [idx] = CONSTANT_Long;
1254 case CONSTANT_Double: {
1255 constant_double *cd = NEW(constant_double);
1258 count_const_pool_len += sizeof(constant_double);
1261 cd -> value = suck_double ();
1262 cptags [idx] = CONSTANT_Double;
1268 case CONSTANT_Utf8: {
1270 /* number of bytes in the bytes array (not string-length) */
1271 u4 length = suck_u2();
1272 cptags [idx] = CONSTANT_Utf8;
1273 /* insert utf-string into the utf-symboltable */
1274 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1275 /* skip bytes of the string */
1276 skip_nbytes(length);
1282 error ("Unkown constant type: %d",(int) t);
1290 /* resolve entries in temporary structures */
1292 while (forward_classes) {
1294 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1296 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1297 /* retrieve class from class-table */
1298 cpinfos [forward_classes -> thisindex] = class_new (name);
1300 forward_classes = forward_classes -> next;
1304 while (forward_strings) {
1306 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1308 log_text("forward_string:");
1309 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1311 log_text("\n------------------"); */
1312 /* resolve utf-string */
1313 cptags [forward_strings -> thisindex] = CONSTANT_String;
1314 cpinfos [forward_strings -> thisindex] = text;
1316 forward_strings = forward_strings -> next;
1319 while (forward_nameandtypes) {
1320 constant_nameandtype *cn = NEW (constant_nameandtype);
1323 count_const_pool_len += sizeof(constant_nameandtype);
1326 /* resolve simple name and descriptor */
1327 cn -> name = class_getconstant
1328 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1329 cn -> descriptor = class_getconstant
1330 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1332 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1333 cpinfos [forward_nameandtypes -> thisindex] = cn;
1335 forward_nameandtypes = forward_nameandtypes -> next;
1339 while (forward_fieldmethints) {
1340 constant_nameandtype *nat;
1341 constant_FMIref *fmi = NEW (constant_FMIref);
1344 count_const_pool_len += sizeof(constant_FMIref);
1346 /* resolve simple name and descriptor */
1347 nat = class_getconstant
1348 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1351 log_text("trying to resolve:");
1352 log_text(nat->name->text);
1353 switch(forward_fieldmethints ->tag) {
1354 case CONSTANT_Fieldref:
1355 log_text("CONSTANT_Fieldref");
1357 case CONSTANT_InterfaceMethodref:
1358 log_text("CONSTANT_InterfaceMethodref");
1360 case CONSTANT_Methodref:
1361 log_text("CONSTANT_Methodref");
1365 fmi -> class = class_getconstant
1366 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1367 fmi -> name = nat -> name;
1368 fmi -> descriptor = nat -> descriptor;
1370 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1371 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1373 switch (forward_fieldmethints -> tag) {
1374 case CONSTANT_Fieldref: /* check validity of descriptor */
1375 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1377 case CONSTANT_InterfaceMethodref:
1378 case CONSTANT_Methodref: /* check validity of descriptor */
1379 checkmethoddescriptor (fmi->descriptor);
1383 forward_fieldmethints = forward_fieldmethints -> next;
1387 /* class_showconstantpool(c); */
1389 dump_release (dumpsize);
1393 /********************** Function: class_load ***********************************
1395 Loads everything interesting about a class from the class file. The
1396 'classinfo' structure must have been allocated previously.
1398 The super class and the interfaces implemented by this class need not be
1399 loaded. The link is set later by the function 'class_link'.
1401 The loaded class is removed from the list 'unloadedclasses' and added to
1402 the list 'unlinkedclasses'.
1404 *******************************************************************************/
1406 static int class_load(classinfo *c)
1412 count_class_loads++;
1415 /* output for debugging purposes */
1417 char logtext[MAXLOGTEXT];
1418 sprintf(logtext, "Loading class: ");
1419 utf_sprint(logtext+strlen(logtext), c->name);
1423 /* load classdata, throw exception on error */
1425 if (!suck_start(c->name)) {
1426 throw_classnotfoundexception2(c->name);
1430 /* check signature */
1431 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1435 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1436 error ("File version %d.%d is not supported",
1437 (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 ();
1450 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1455 /* retrieve superclass */
1456 if ( (i = suck_u2 () ) ) {
1457 c -> super = class_getconstant (c, i, CONSTANT_Class);
1463 /* retrieve interfaces */
1464 c -> interfacescount = suck_u2 ();
1465 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1466 for (i=0; i < c -> interfacescount; i++) {
1467 c -> interfaces [i] =
1468 class_getconstant (c, suck_u2(), CONSTANT_Class);
1472 c -> fieldscount = suck_u2 ();
1473 /* utf_display(c->name);
1474 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1476 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1477 for (i=0; i < c -> fieldscount; i++) {
1478 field_load (&(c->fields[i]), c);
1482 c -> methodscount = suck_u2 ();
1483 c -> methods = MNEW (methodinfo, c -> methodscount);
1484 for (i=0; i < c -> methodscount; i++) {
1485 method_load (&(c -> methods [i]), c);
1489 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1490 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1491 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1494 /* load variable-length attribute structures */
1495 attribute_load (suck_u2(), c);
1500 /* remove class from list of unloaded classes and
1501 add to list of unlinked classes */
1502 list_remove (&unloadedclasses, c);
1503 list_addlast (&unlinkedclasses, c);
1510 /************** internal Function: class_highestinterface ***********************
1512 Used by the function class_link to determine the amount of memory needed
1513 for the interface table.
1515 *******************************************************************************/
1517 static s4 class_highestinterface (classinfo *c)
1522 if ( ! (c->flags & ACC_INTERFACE) ) {
1523 char logtext[MAXLOGTEXT];
1524 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1525 utf_sprint (logtext+strlen(logtext), c->name);
1530 for (i=0; i<c->interfacescount; i++) {
1531 s4 h2 = class_highestinterface (c->interfaces[i]);
1538 /* class_addinterface **********************************************************
1540 Is needed by class_link for adding a VTBL to a class. All interfaces
1541 implemented by ic are added as well.
1543 *******************************************************************************/
1545 static void class_addinterface (classinfo *c, classinfo *ic)
1549 vftbl *vftbl = c->vftbl;
1551 if (i >= vftbl->interfacetablelength)
1552 panic ("Inernal error: interfacetable overflow");
1553 if (vftbl->interfacetable[-i])
1556 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1557 vftbl->interfacevftbllength[i] = 1;
1558 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1559 vftbl->interfacetable[-i][0] = NULL;
1562 vftbl->interfacevftbllength[i] = ic->methodscount;
1563 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1566 count_vftbl_len += sizeof(methodptr) *
1567 (ic->methodscount + (ic->methodscount == 0));
1570 for (j=0; j<ic->methodscount; j++) {
1573 for (m = 0; m < sc->methodscount; m++) {
1574 methodinfo *mi = &(sc->methods[m]);
1575 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1576 vftbl->interfacetable[-i][j] =
1577 vftbl->table[mi->vftblindex];
1587 for (j = 0; j < ic->interfacescount; j++)
1588 class_addinterface(c, ic->interfaces[j]);
1592 /******************* Function: class_new_array *********************************
1594 This function is called by class_new to setup an array class.
1596 *******************************************************************************/
1599 class_new_array(classinfo *c)
1601 classinfo *comp = NULL;
1605 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1607 /* Array classes are not loaded from classfiles. */
1608 list_remove (&unloadedclasses, c);
1610 /* Check array class name */
1611 namelen = c->name->blength;
1612 if (namelen < 2 || c->name->text[0] != '[')
1613 panic("Invalid array class name.");
1615 /* Check the component type */
1616 switch (c->name->text[1]) {
1618 /* c is an array of arrays. We have to create the component class. */
1619 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1623 /* c is an array of objects. */
1624 if (namelen < 4 || c->name->text[namelen-1] != ';')
1625 panic("Invalid array class name.");
1626 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1630 /* Setup the array class */
1631 c->super = class_java_lang_Object;
1633 c->interfacescount = 2;
1634 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1635 c->interfaces[0] = class_java_lang_Cloneable;
1636 c->interfaces[1] = class_java_io_Serializable;
1638 c->methodscount = 1;
1639 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1642 memset(clone,0,sizeof(methodinfo));
1643 clone->flags = ACC_PUBLIC; /* XXX protected? */
1644 clone->name = utf_new_char("clone");
1645 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1647 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1648 clone->monoPoly = MONO; /* XXX should be poly? */
1650 /* XXX: field: length? */
1652 /* The array class has to be linked */
1653 list_addlast(&unlinkedclasses,c);
1656 * Array classes which are created after the other classes have been
1657 * loaded and linked are linked explicitely.
1662 loader_load(c->name);
1665 /****************** Function: class_link_array *********************************
1667 This function is called by class_link to create the
1668 arraydescriptor for an array class.
1670 This function returns NULL if the array cannot be linked because
1671 the component type has not been linked yet.
1673 *******************************************************************************/
1677 class_link_array(classinfo *c)
1679 classinfo *comp = NULL;
1680 int namelen = c->name->blength;
1681 arraydescriptor *desc;
1684 /* Check the component type */
1685 switch (c->name->text[1]) {
1687 /* c is an array of arrays. */
1688 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1689 if (!comp) panic("Could not find component array class.");
1693 /* c is an array of objects. */
1694 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1695 if (!comp) panic("Could not find component class.");
1699 /* If the component type has not been linked return NULL */
1700 if (comp && !comp->linked)
1703 /* Allocate the arraydescriptor */
1704 desc = NEW(arraydescriptor);
1707 /* c is an array of references */
1708 desc->arraytype = ARRAYTYPE_OBJECT;
1709 desc->componentsize = sizeof(void*);
1710 desc->dataoffset = OFFSET(java_objectarray,data);
1712 compvftbl = comp->vftbl;
1714 panic("Component class has no vftbl.");
1715 desc->componentvftbl = compvftbl;
1717 if (compvftbl->arraydesc) {
1718 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1719 desc->dimension = compvftbl->arraydesc->dimension + 1;
1720 desc->elementtype = compvftbl->arraydesc->elementtype;
1723 desc->elementvftbl = compvftbl;
1724 desc->dimension = 1;
1725 desc->elementtype = ARRAYTYPE_OBJECT;
1729 /* c is an array of a primitive type */
1730 switch (c->name->text[1]) {
1731 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1732 desc->dataoffset = OFFSET(java_booleanarray,data);
1733 desc->componentsize = sizeof(u1); break;
1734 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1735 desc->dataoffset = OFFSET(java_bytearray,data);
1736 desc->componentsize = sizeof(u1); break;
1737 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1738 desc->dataoffset = OFFSET(java_chararray,data);
1739 desc->componentsize = sizeof(u2); break;
1740 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1741 desc->dataoffset = OFFSET(java_doublearray,data);
1742 desc->componentsize = sizeof(double); break;
1743 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1744 desc->dataoffset = OFFSET(java_floatarray,data);
1745 desc->componentsize = sizeof(float); break;
1746 case 'I': desc->arraytype = ARRAYTYPE_INT;
1747 desc->dataoffset = OFFSET(java_intarray,data);
1748 desc->componentsize = sizeof(s4); break;
1749 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1750 desc->dataoffset = OFFSET(java_longarray,data);
1751 desc->componentsize = sizeof(s8); break;
1752 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1753 desc->dataoffset = OFFSET(java_shortarray,data);
1754 desc->componentsize = sizeof(s2); break;
1756 panic("Invalid array class name");
1759 desc->componentvftbl = NULL;
1760 desc->elementvftbl = NULL;
1761 desc->dimension = 1;
1762 desc->elementtype = desc->arraytype;
1768 /********************** Function: class_link ***********************************
1770 Tries to link a class. The super class and every implemented interface must
1771 already have been linked. The function calculates the length in bytes that
1772 an instance of this class requires as well as the VTBL for methods and
1775 If the class can be linked, it is removed from the list 'unlinkedclasses'
1776 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1779 Attention: If cyclical class definitions are encountered, the program gets
1780 into an infinite loop (we'll have to work that out)
1782 *******************************************************************************/
1784 void class_link(classinfo *c)
1786 s4 supervftbllength; /* vftbllegnth of super class */
1787 s4 vftbllength; /* vftbllength of current class */
1788 s4 interfacetablelength; /* interface table length */
1789 classinfo *super = c->super; /* super class */
1790 classinfo *ic, *c2; /* intermediate class variables */
1791 vftbl *v; /* vftbl of current class */
1792 s4 i; /* interface/method/field counter */
1793 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1796 /* check if all superclasses are already linked, if not put c at end of
1797 unlinked list and return. Additionally initialize class fields. */
1799 /* check interfaces */
1801 for (i = 0; i < c->interfacescount; i++) {
1802 ic = c->interfaces[i];
1804 list_remove(&unlinkedclasses, c);
1805 list_addlast(&unlinkedclasses, c);
1810 /* check super class */
1812 if (super == NULL) { /* class java.long.Object */
1814 c->classUsed = USED; /* Object class is always used CO-RT*/
1815 c -> impldBy = NULL;
1816 c->instancesize = sizeof(java_objectheader);
1818 vftbllength = supervftbllength = 0;
1820 c->finalizer = NULL;
1823 if (!super->linked) {
1824 list_remove(&unlinkedclasses, c);
1825 list_addlast(&unlinkedclasses, c);
1829 /* handle array classes */
1830 if (c->name->text[0] == '[')
1831 if ((arraydesc = class_link_array(c)) == NULL) {
1832 list_remove(&unlinkedclasses, c);
1833 list_addlast(&unlinkedclasses, c);
1837 if (c->flags & ACC_INTERFACE)
1838 c->index = interfaceindex++;
1840 c->index = super->index + 1;
1842 c->instancesize = super->instancesize;
1844 vftbllength = supervftbllength = super->vftbl->vftbllength;
1846 c->finalizer = super->finalizer;
1851 char logtext[MAXLOGTEXT];
1852 sprintf (logtext, "Linking Class: ");
1853 utf_sprint (logtext+strlen(logtext), c->name );
1857 /* compute vftbl length */
1859 for (i = 0; i < c->methodscount; i++) {
1860 methodinfo *m = &(c->methods[i]);
1862 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1863 classinfo *sc = super;
1866 for (j = 0; j < sc->methodscount; j++) {
1867 if (method_canoverwrite(m, &(sc->methods[j]))) {
1868 m->vftblindex = sc->methods[j].vftblindex;
1869 goto foundvftblindex;
1874 m->vftblindex = (vftbllength++);
1880 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1883 /* compute interfacetable length */
1885 interfacetablelength = 0;
1888 for (i = 0; i < c2->interfacescount; i++) {
1889 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1890 if (h > interfacetablelength)
1891 interfacetablelength = h;
1896 /* allocate virtual function table */
1898 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1899 (vftbllength - 1) + sizeof(methodptr*) *
1900 (interfacetablelength - (interfacetablelength > 0)));
1901 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1902 (interfacetablelength > 1));
1903 c->header.vftbl = c->vftbl = v;
1905 v->vftbllength = vftbllength;
1906 v->interfacetablelength = interfacetablelength;
1907 v->arraydesc = arraydesc;
1909 /* store interface index in vftbl */
1910 if (c->flags & ACC_INTERFACE)
1911 v->baseval = -(c->index);
1913 /* copy virtual function table of super class */
1915 for (i = 0; i < supervftbllength; i++)
1916 v->table[i] = super->vftbl->table[i];
1918 /* add method stubs into virtual function table */
1920 for (i = 0; i < c->methodscount; i++) {
1921 methodinfo *m = &(c->methods[i]);
1922 if (!(m->flags & ACC_STATIC)) {
1923 v->table[m->vftblindex] = m->stubroutine;
1927 /* compute instance size and offset of each field */
1929 for (i = 0; i < c->fieldscount; i++) {
1931 fieldinfo *f = &(c->fields[i]);
1933 if (!(f->flags & ACC_STATIC) ) {
1934 dsize = desc_typesize (f->descriptor);
1935 c->instancesize = ALIGN (c->instancesize, dsize);
1936 f->offset = c->instancesize;
1937 c->instancesize += dsize;
1941 /* initialize interfacetable and interfacevftbllength */
1943 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1946 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1949 for (i = 0; i < interfacetablelength; i++) {
1950 v->interfacevftbllength[i] = 0;
1951 v->interfacetable[-i] = NULL;
1954 /* add interfaces */
1956 for (c2 = c; c2 != NULL; c2 = c2->super)
1957 for (i = 0; i < c2->interfacescount; i++) {
1958 class_addinterface (c, c2->interfaces[i]);
1961 /* add finalizer method (not for java.lang.Object) */
1963 if (super != NULL) {
1965 static utf *finame = NULL;
1966 static utf *fidesc = NULL;
1969 finame = utf_finalize;
1971 fidesc = utf_fidesc;
1973 fi = class_findmethod (c, finame, fidesc);
1975 if (!(fi->flags & ACC_STATIC)) {
1985 list_remove (&unlinkedclasses, c);
1986 list_addlast (&linkedclasses, c);
1991 /******************* Function: class_freepool **********************************
1993 Frees all resources used by this classes Constant Pool.
1995 *******************************************************************************/
1997 static void class_freecpool (classinfo *c)
2003 for (idx=0; idx < c->cpcount; idx++) {
2004 tag = c->cptags[idx];
2005 info = c->cpinfos[idx];
2009 case CONSTANT_Fieldref:
2010 case CONSTANT_Methodref:
2011 case CONSTANT_InterfaceMethodref:
2012 FREE (info, constant_FMIref);
2014 case CONSTANT_Integer:
2015 FREE (info, constant_integer);
2017 case CONSTANT_Float:
2018 FREE (info, constant_float);
2021 FREE (info, constant_long);
2023 case CONSTANT_Double:
2024 FREE (info, constant_double);
2026 case CONSTANT_NameAndType:
2027 FREE (info, constant_nameandtype);
2033 MFREE (c -> cptags, u1, c -> cpcount);
2034 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2038 /*********************** Function: class_free **********************************
2040 Frees all resources used by the class.
2042 *******************************************************************************/
2044 static void class_free (classinfo *c)
2049 class_freecpool (c);
2051 MFREE (c->interfaces, classinfo*, c->interfacescount);
2053 for (i = 0; i < c->fieldscount; i++)
2054 field_free(&(c->fields[i]));
2056 for (i = 0; i < c->methodscount; i++)
2057 method_free(&(c->methods[i]));
2058 MFREE (c->methods, methodinfo, c->methodscount);
2060 if ((v = c->vftbl) != NULL) {
2062 mem_free(v->arraydesc,sizeof(arraydescriptor));
2064 for (i = 0; i < v->interfacetablelength; i++) {
2065 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2067 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2069 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2070 sizeof(methodptr*) * (v->interfacetablelength -
2071 (v->interfacetablelength > 0));
2072 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2073 (v->interfacetablelength > 1));
2077 if (c->innerclasscount)
2078 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2080 /* if (c->classvftbl)
2081 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2083 FREE (c, classinfo);
2086 /************************* Function: class_findfield ***************************
2088 Searches a 'classinfo' structure for a field having the given name and
2091 *******************************************************************************/
2094 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2099 for (i = 0; i < c->fieldscount; i++) {
2100 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2101 return &(c->fields[i]);
2104 panic ("Can not find field given in CONSTANT_Fieldref");
2109 /************************* Function: class_findmethod **************************
2111 Searches a 'classinfo' structure for a method having the given name and
2112 type and returns the index in the class info structure.
2113 If type is NULL, it is ignored.
2115 *******************************************************************************/
2117 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2120 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2122 int buffer_len, pos;
2124 #ifdef JOWENN_DEBUG1
2127 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2129 buffer = MNEW(char, buffer_len);
2131 strcpy(buffer, "class_findmethod: method:");
2132 utf_sprint(buffer+strlen(buffer), name);
2133 strcpy(buffer+strlen(buffer), ", desc: ");
2134 utf_sprint(buffer+strlen(buffer), desc);
2135 strcpy(buffer+strlen(buffer), ", classname: ");
2136 utf_sprint(buffer+strlen(buffer), c->name);
2140 MFREE(buffer, char, buffer_len);
2142 for (i = 0; i < c->methodscount; i++) {
2143 #ifdef JOWENN_DEBUG2
2145 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2147 buffer = MNEW(char, buffer_len);
2149 strcpy(buffer, "class_findmethod: comparing to method:");
2150 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2151 strcpy(buffer+strlen(buffer), ", desc: ");
2152 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2156 MFREE(buffer, char, buffer_len);
2160 if ((c->methods[i].name == name) && ((desc == NULL) ||
2161 (c->methods[i].descriptor == desc)))
2164 #ifdef JOWENN_DEBUG2
2165 class_showconstantpool(c);
2166 log_text("class_findmethod: returning NULL");
2173 /************************* Function: class_findmethod **************************
2175 Searches a 'classinfo' structure for a method having the given name and
2177 If type is NULL, it is ignored.
2179 *******************************************************************************/
2181 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2185 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2187 int buffer_len, pos;
2189 #ifdef JOWENN_DEBUG1
2192 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2194 buffer = MNEW(char, buffer_len);
2196 strcpy(buffer, "class_findmethod: method:");
2197 utf_sprint(buffer+strlen(buffer), name);
2198 strcpy(buffer+strlen(buffer), ", desc: ");
2199 utf_sprint(buffer+strlen(buffer), desc);
2200 strcpy(buffer+strlen(buffer), ", classname: ");
2201 utf_sprint(buffer+strlen(buffer), c->name);
2205 MFREE(buffer, char, buffer_len);
2207 for (i = 0; i < c->methodscount; i++) {
2208 #ifdef JOWENN_DEBUG2
2210 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2212 buffer = MNEW(char, buffer_len);
2214 strcpy(buffer, "class_findmethod: comparing to method:");
2215 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2216 strcpy(buffer+strlen(buffer), ", desc: ");
2217 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2221 MFREE(buffer, char, buffer_len);
2225 if ((c->methods[i].name == name) && ((desc == NULL) ||
2226 (c->methods[i].descriptor == desc)))
2227 return &(c->methods[i]);
2229 #ifdef JOWENN_DEBUG2
2230 class_showconstantpool(c);
2231 log_text("class_findmethod: returning NULL");
2235 s4 idx=class_findmethodIndex(c,name,desc);
2236 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2237 if (idx==-1) return NULL;
2238 return &(c->methods[idx]);
2246 /************************* Function: class_findmethod_approx ******************
2248 like class_findmethod but ignores the return value when comparing the
2251 *******************************************************************************/
2253 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2257 for (i = 0; i < c->methodscount; i++)
2258 if (c->methods[i].name == name) {
2259 utf *meth_descr = c->methods[i].descriptor;
2263 return &(c->methods[i]);
2265 if (desc->blength <= meth_descr->blength) {
2266 /* current position in utf text */
2267 char *desc_utf_ptr = desc->text;
2268 char *meth_utf_ptr = meth_descr->text;
2269 /* points behind utf strings */
2270 char *desc_end = utf_end(desc);
2271 char *meth_end = utf_end(meth_descr);
2274 /* compare argument types */
2275 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2277 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2278 break; /* no match */
2281 return &(c->methods[i]); /* all parameter types equal */
2289 /***************** Function: class_resolvemethod_approx ***********************
2291 Searches a class and every super class for a method (without paying
2292 attention to the return value)
2294 *******************************************************************************/
2296 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2299 /* search for method (ignore returntype) */
2300 methodinfo *m = class_findmethod_approx (c, name, desc);
2303 /* search superclass */
2310 /************************* Function: class_resolvemethod ***********************
2312 Searches a class and every super class for a method.
2314 *******************************************************************************/
2316 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2319 methodinfo *m = class_findmethod(c, name, desc);
2321 /* search superclass */
2329 /************************* Function: class_issubclass **************************
2331 Checks if sub is a descendant of super.
2333 *******************************************************************************/
2335 bool class_issubclass(classinfo *sub, classinfo *super)
2338 if (!sub) return false;
2339 if (sub==super) return true;
2346 /****************** Initialization function for classes ******************
2348 In Java, every class can have a static initialization function. This
2349 function has to be called BEFORE calling other methods or accessing static
2352 *******************************************************************************/
2355 extern int blockInts;
2358 void class_init(classinfo *c)
2361 java_objectheader *exceptionptr;
2366 if (!makeinitializations)
2370 c -> initialized = true;
2375 count_class_inits++;
2379 class_init (c->super);
2380 for (i=0; i < c->interfacescount; i++)
2381 class_init(c->interfaces[i]); /* real */
2383 m = class_findmethod (c, utf_clinit, utf_fidesc);
2386 char logtext[MAXLOGTEXT];
2387 sprintf (logtext, "Class ");
2388 utf_sprint (logtext+strlen(logtext), c->name);
2389 sprintf (logtext+strlen(logtext), " has no initializer");
2392 /* goto callinitialize;*/
2396 if (! (m->flags & ACC_STATIC))
2397 panic ("Class initializer is not static!");
2400 char logtext[MAXLOGTEXT];
2401 sprintf (logtext, "Starting initializer for class: ");
2402 utf_sprint (logtext+strlen(logtext), c->name);
2411 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2414 assert(blockInts == 0);
2419 printf ("#### Initializer of ");
2420 utf_display (c->name);
2421 printf (" has thrown: ");
2422 utf_display (exceptionptr->vftbl->class->name);
2428 char logtext[MAXLOGTEXT];
2429 sprintf (logtext, "Finished initializer for class: ");
2430 utf_sprint (logtext+strlen(logtext), c->name);
2433 if (c->name == utf_systemclass) {
2434 /* class java.lang.System requires explicit initialization */
2437 printf ("#### Initializing class System");
2439 /* find initializing method */
2440 m = class_findmethod (c,
2441 utf_initsystemclass,
2445 /* no method found */
2446 /* printf("initializeSystemClass failed"); */
2454 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2457 assert(blockInts == 0);
2462 printf ("#### initializeSystemClass has thrown: ");
2463 utf_display (exceptionptr->vftbl->class->name);
2474 /********* Function: find_class_method_constant *********/
2475 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2480 for (i=0; i<c->cpcount; i++) {
2482 e = c -> cpinfos [i];
2485 switch (c -> cptags [i]) {
2486 case CONSTANT_Methodref:
2488 constant_FMIref *fmi = e;
2489 if ( (fmi->class->name == c1)
2490 && (fmi->name == m1)
2491 && (fmi->descriptor == d1)) {
2498 case CONSTANT_InterfaceMethodref:
2500 constant_FMIref *fmi = e;
2501 if ( (fmi->class->name == c1)
2502 && (fmi->name == m1)
2503 && (fmi->descriptor == d1)) {
2517 void class_showconstanti(classinfo *c, int ii)
2523 printf ("#%d: ", (int) i);
2525 switch (c->cptags [i]) {
2526 case CONSTANT_Class:
2527 printf("Classreference -> ");
2528 utf_display(((classinfo*)e)->name);
2531 case CONSTANT_Fieldref:
2532 printf("Fieldref -> "); goto displayFMIi;
2533 case CONSTANT_Methodref:
2534 printf("Methodref -> "); goto displayFMIi;
2535 case CONSTANT_InterfaceMethodref:
2536 printf("InterfaceMethod -> "); goto displayFMIi;
2539 constant_FMIref *fmi = e;
2540 utf_display(fmi->class->name);
2542 utf_display(fmi->name);
2544 utf_display(fmi->descriptor);
2548 case CONSTANT_String:
2549 printf("String -> ");
2552 case CONSTANT_Integer:
2553 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2555 case CONSTANT_Float:
2556 printf("Float -> %f", ((constant_float*)e)->value);
2558 case CONSTANT_Double:
2559 printf("Double -> %f", ((constant_double*)e)->value);
2563 u8 v = ((constant_long*)e)->value;
2565 printf("Long -> %ld", (long int) v);
2567 printf("Long -> HI: %ld, LO: %ld\n",
2568 (long int) v.high, (long int) v.low);
2572 case CONSTANT_NameAndType:
2574 constant_nameandtype *cnt = e;
2575 printf("NameAndType: ");
2576 utf_display(cnt->name);
2578 utf_display(cnt->descriptor);
2586 panic("Invalid type of ConstantPool-Entry");
2593 void class_showconstantpool (classinfo *c)
2598 printf ("---- dump of constant pool ----\n");
2600 for (i=0; i<c->cpcount; i++) {
2601 printf ("#%d: ", (int) i);
2603 e = c -> cpinfos [i];
2606 switch (c -> cptags [i]) {
2607 case CONSTANT_Class:
2608 printf ("Classreference -> ");
2609 utf_display ( ((classinfo*)e) -> name );
2612 case CONSTANT_Fieldref:
2613 printf ("Fieldref -> "); goto displayFMI;
2614 case CONSTANT_Methodref:
2615 printf ("Methodref -> "); goto displayFMI;
2616 case CONSTANT_InterfaceMethodref:
2617 printf ("InterfaceMethod -> "); goto displayFMI;
2620 constant_FMIref *fmi = e;
2621 utf_display ( fmi->class->name );
2623 utf_display ( fmi->name);
2625 utf_display ( fmi->descriptor );
2629 case CONSTANT_String:
2630 printf ("String -> ");
2633 case CONSTANT_Integer:
2634 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2636 case CONSTANT_Float:
2637 printf ("Float -> %f", ((constant_float*)e) -> value);
2639 case CONSTANT_Double:
2640 printf ("Double -> %f", ((constant_double*)e) -> value);
2644 u8 v = ((constant_long*)e) -> value;
2646 printf ("Long -> %ld", (long int) v);
2648 printf ("Long -> HI: %ld, LO: %ld\n",
2649 (long int) v.high, (long int) v.low);
2653 case CONSTANT_NameAndType:
2655 constant_nameandtype *cnt = e;
2656 printf ("NameAndType: ");
2657 utf_display (cnt->name);
2659 utf_display (cnt->descriptor);
2663 printf ("Utf8 -> ");
2667 panic ("Invalid type of ConstantPool-Entry");
2677 /********** Function: class_showmethods (debugging only) *************/
2679 void class_showmethods (classinfo *c)
2683 printf ("--------- Fields and Methods ----------------\n");
2684 printf ("Flags: "); printflags (c->flags); printf ("\n");
2686 printf ("This: "); utf_display (c->name); printf ("\n");
2688 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2690 printf ("Index: %d\n", c->index);
2692 printf ("interfaces:\n");
2693 for (i=0; i < c-> interfacescount; i++) {
2695 utf_display (c -> interfaces[i] -> name);
2696 printf (" (%d)\n", c->interfaces[i] -> index);
2699 printf ("fields:\n");
2700 for (i=0; i < c -> fieldscount; i++) {
2701 field_display (&(c -> fields[i]));
2704 printf ("methods:\n");
2705 for (i=0; i < c -> methodscount; i++) {
2706 methodinfo *m = &(c->methods[i]);
2707 if ( !(m->flags & ACC_STATIC))
2708 printf ("vftblindex: %d ", m->vftblindex);
2710 method_display ( m );
2714 printf ("Virtual function table:\n");
2715 for (i=0; i<c->vftbl->vftbllength; i++) {
2716 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2723 /******************************************************************************/
2724 /******************* General functions for the class loader *******************/
2725 /******************************************************************************/
2727 /********************* Function: loader_load ***********************************
2729 Loads and links the class desired class and each class and interface
2731 Returns: a pointer to this class
2733 *******************************************************************************/
2735 static int loader_load_running = 0;
2737 classinfo *loader_load (utf *topname)
2741 long int starttime=0,stoptime=0;
2743 /* avoid recursive calls */
2744 if (loader_load_running)
2745 return class_new(topname);
2746 loader_load_running++;
2748 intsDisable(); /* schani */
2751 starttime = getcputime();
2753 top = class_new (topname);
2756 while ( (c = list_first(&unloadedclasses)) ) {
2757 if (!class_load (c)) {
2758 list_remove (&unloadedclasses, c);
2764 while ( (c = list_first(&unlinkedclasses)) ) {
2769 loader_compute_subclasses();
2772 if (getloadingtime) {
2773 stoptime = getcputime();
2774 loadingtime += (stoptime-starttime);
2778 loader_load_running--;
2780 /* check if a former loader_load call tried to load/link the class and failed.
2781 This is needed because the class didn't appear in the undloadclasses or unlinkedclasses list during this class; */
2784 throw_classnotfoundexception2(top->name);
2786 } else if (!top->linked) {
2787 throw_linkageerror2(top->name);
2792 intsRestore(); /* schani */
2798 /**************** function: create_primitive_classes ***************************
2800 create classes representing primitive types
2802 ********************************************************************************/
2805 void create_primitive_classes()
2809 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2810 /* create primitive class */
2811 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2812 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2813 c -> impldBy = NULL;
2815 /* prevent loader from loading primitive class */
2816 list_remove (&unloadedclasses, c);
2818 /* add to unlinked classes */
2819 list_addlast (&unlinkedclasses, c);
2820 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
2823 primitivetype_table[i].class_primitive = c;
2825 /* create class for wrapping the primitive type */
2826 primitivetype_table[i].class_wrap =
2827 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2828 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2829 primitivetype_table[i].class_wrap -> impldBy = NULL;
2831 /* create the primitive array class */
2832 if (primitivetype_table[i].arrayname) {
2833 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2834 primitivetype_table[i].arrayclass = c;
2836 if (!c->linked) class_link(c);
2837 primitivetype_table[i].arrayvftbl = c->vftbl;
2842 /**************** function: class_primitive_from_sig ***************************
2844 return the primitive class indicated by the given signature character
2846 If the descriptor does not indicate a valid primitive type the
2847 return value is NULL.
2849 ********************************************************************************/
2851 classinfo *class_primitive_from_sig(char sig)
2854 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2855 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2856 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2857 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2858 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2859 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2860 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2861 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2862 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2867 /****************** function: class_from_descriptor ****************************
2869 return the class indicated by the given descriptor
2871 utf_ptr....first character of descriptor
2872 end_ptr....first character after the end of the string
2873 next.......if non-NULL, *next is set to the first character after
2875 mode.......what to do if a class descriptor is parsed successfully:
2876 CLASSLOAD_SKIP...skip it and return something != NULL
2877 CLASSLOAD_NEW....get classinfo * via class_new
2878 CLASSLOAD_LOAD...get classinfo * via loader_load
2880 If the descriptor is invalid the return value is NULL
2882 ********************************************************************************/
2884 classinfo *class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
2886 char *start = utf_ptr;
2890 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
2891 if (error) return NULL;
2892 if (next) *next = utf_ptr;
2900 if (mode == CLASSLOAD_SKIP) return class_java_lang_Object;
2901 name = utf_new(start,utf_ptr-start);
2902 return (mode == CLASSLOAD_LOAD) ? loader_load(name) : class_new(name);
2904 return class_primitive_from_sig(*start);
2908 /*************** function: create_pseudo_classes *******************************
2910 create pseudo classes used by the typechecker
2912 ********************************************************************************/
2915 create_pseudo_classes()
2917 /* pseudo class for Arraystubs (extends java.lang.Object) */
2919 pseudo_class_Arraystub = class_new( utf_new_char("$ARRAYSTUB$") );
2920 list_remove(&unloadedclasses,pseudo_class_Arraystub);
2922 pseudo_class_Arraystub->super = class_java_lang_Object;
2923 pseudo_class_Arraystub->interfacescount = 2;
2924 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
2925 pseudo_class_Arraystub->interfaces[0] =
2926 class_java_lang_Cloneable;
2927 pseudo_class_Arraystub->interfaces[1] =
2928 class_java_io_Serializable;
2930 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
2931 class_link(pseudo_class_Arraystub);
2933 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
2935 /* pseudo class representing the null type */
2937 pseudo_class_Null = class_new( utf_new_char("$NULL$") );
2938 list_remove(&unloadedclasses,pseudo_class_Null);
2940 pseudo_class_Null->super = class_java_lang_Object;
2942 list_addlast(&unlinkedclasses,pseudo_class_Null);
2943 class_link(pseudo_class_Null);
2945 /* pseudo class representing new uninitialized objects */
2947 pseudo_class_New = class_new( utf_new_char("$NEW$") );
2948 list_remove(&unloadedclasses,pseudo_class_New);
2950 pseudo_class_New->super = class_java_lang_Object;
2952 list_addlast(&unlinkedclasses,pseudo_class_New);
2953 class_link(pseudo_class_New);
2956 /********************** Function: loader_init **********************************
2958 Initializes all lists and loads all classes required for the system or the
2961 *******************************************************************************/
2963 void loader_init (u1 * stackbottom)
2968 log_text("Entering loader_init");
2971 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2972 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2973 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2975 /* create utf-symbols for pointer comparison of frequently used strings */
2976 utf_innerclasses = utf_new_char("InnerClasses");
2977 utf_constantvalue = utf_new_char("ConstantValue");
2978 utf_code = utf_new_char("Code");
2979 utf_finalize = utf_new_char("finalize");
2980 utf_fidesc = utf_new_char("()V");
2981 utf_clinit = utf_new_char("<clinit>");
2982 utf_initsystemclass = utf_new_char("initializeSystemClass");
2983 utf_systemclass = utf_new_char("java/lang/System");
2984 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
2985 utf_initialize =utf_new_char("initialize");
2986 utf_initializedesc =utf_new_char("(I)V");
2988 utf_vmclass =utf_new_char("java/lang/VMClass");
2990 /* create some important classes */
2991 /* These classes have to be created now because the classinfo
2992 * pointers are used in the loading code.
2994 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
2995 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
2996 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
2997 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
2999 log_text("loader_init: java/lang/Object");
3000 /* load the classes which were created above */
3001 loader_load (class_java_lang_Object->name);
3003 loader_inited=1; /*JOWENN*/
3005 class_java_lang_Throwable =
3006 loader_load( utf_new_char("java/lang/Throwable") );
3008 log_text("loader_init: loader_load: java/lang/ClassCastException");
3009 class_java_lang_ClassCastException =
3010 loader_load ( utf_new_char ("java/lang/ClassCastException") );
3011 class_java_lang_NullPointerException =
3012 loader_load ( utf_new_char ("java/lang/NullPointerException") );
3013 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
3014 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
3015 class_java_lang_NegativeArraySizeException = loader_load (
3016 utf_new_char ("java/lang/NegativeArraySizeException") );
3017 class_java_lang_OutOfMemoryError = loader_load (
3018 utf_new_char ("java/lang/OutOfMemoryError") );
3019 class_java_lang_ArrayStoreException =
3020 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
3021 class_java_lang_ArithmeticException =
3022 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
3023 class_java_lang_ThreadDeath = /* schani */
3024 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
3025 /* create classes representing primitive types */
3026 create_primitive_classes();
3028 /* create classes used by the typechecker */
3029 create_pseudo_classes();
3031 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3032 stringtable_update();
3040 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3041 proto_java_lang_ClassCastException =
3042 builtin_new(class_java_lang_ClassCastException);
3043 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3045 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3047 proto_java_lang_NullPointerException =
3048 builtin_new(class_java_lang_NullPointerException);
3049 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3050 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3052 proto_java_lang_ArrayIndexOutOfBoundsException =
3053 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3054 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3056 proto_java_lang_NegativeArraySizeException =
3057 builtin_new(class_java_lang_NegativeArraySizeException);
3058 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3060 proto_java_lang_OutOfMemoryError =
3061 builtin_new(class_java_lang_OutOfMemoryError);
3062 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3064 proto_java_lang_ArithmeticException =
3065 builtin_new(class_java_lang_ArithmeticException);
3066 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3068 proto_java_lang_ArrayStoreException =
3069 builtin_new(class_java_lang_ArrayStoreException);
3070 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3072 proto_java_lang_ThreadDeath = /* schani */
3073 builtin_new(class_java_lang_ThreadDeath);
3074 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3083 /********************* Function: loader_initclasses ****************************
3085 Initializes all loaded but uninitialized classes
3087 *******************************************************************************/
3089 void loader_initclasses ()
3093 intsDisable(); /* schani */
3095 if (makeinitializations) {
3096 c = list_first (&linkedclasses);
3099 c = list_next (&linkedclasses, c);
3103 intsRestore(); /* schani */
3106 static s4 classvalue;
3108 static void loader_compute_class_values (classinfo *c)
3112 c->vftbl->baseval = ++classvalue;
3115 while (subs != NULL) {
3116 loader_compute_class_values(subs);
3117 subs = subs->nextsub;
3119 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3124 for (i = 0; i < c->index; i++)
3126 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3127 utf_display(c->name);
3135 void loader_compute_subclasses ()
3139 intsDisable(); /* schani */
3141 c = list_first (&linkedclasses);
3143 if (!(c->flags & ACC_INTERFACE)) {
3147 c = list_next (&linkedclasses, c);
3150 c = list_first (&linkedclasses);
3152 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3153 c->nextsub = c->super->sub;
3156 c = list_next (&linkedclasses, c);
3159 loader_compute_class_values(class_java_lang_Object);
3161 intsRestore(); /* schani */
3166 /******************** function classloader_buffer ******************************
3168 sets buffer for reading classdata
3170 *******************************************************************************/
3172 void classload_buffer(u1 *buf, int len)
3175 classbuffer_size = len;
3176 classbuf_pos = buf - 1;
3180 /******************** Function: loader_close ***********************************
3184 *******************************************************************************/
3186 void loader_close ()
3190 while ( (c=list_first(&unloadedclasses)) ) {
3191 list_remove (&unloadedclasses,c);
3194 while ( (c=list_first(&unlinkedclasses)) ) {
3195 list_remove (&unlinkedclasses,c);
3198 while ( (c=list_first(&linkedclasses)) ) {
3199 list_remove (&linkedclasses,c);
3206 * These are local overrides for various environment variables in Emacs.
3207 * Please do not remove this and leave it at the end of the file, where
3208 * Emacs will automagically detect them.
3209 * ---------------------------------------------------------------------
3212 * indent-tabs-mode: t