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 724 2003-12-09 18:56:11Z 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 #define ASSERT_LEFT(len) \
196 do {if (((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
197 panic("Unexpected end of classfile"); } while(0)
199 /* transfer block of classfile data into a buffer */
201 #define suck_nbytes(buffer,len) \
202 do {ASSERT_LEFT(len); \
203 memcpy(buffer,classbuf_pos+1,len); \
204 classbuf_pos+=len;} while (0)
206 /* skip block of classfile data */
208 #define skip_nbytes(len) \
209 do {ASSERT_LEFT(len); \
210 classbuf_pos+=len;} while(0)
215 return *++classbuf_pos;
219 u1 a=suck_u1(), b=suck_u1();
220 return ((u2)a<<8)+(u2)b;
224 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
225 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
227 #define suck_s8() (s8) suck_u8()
228 #define suck_s2() (s2) suck_u2()
229 #define suck_s4() (s4) suck_u4()
230 #define suck_s1() (s1) suck_u1()
233 /* get u8 from classfile data */
240 return (hi << 32) + lo;
250 /* get float from classfile data */
251 static float suck_float()
258 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
259 memcpy((u1*) (&f), buffer, 4);
261 suck_nbytes((u1*) (&f), 4);
264 PANICIF (sizeof(float) != 4, "Incompatible float-format");
270 /* get double from classfile data */
271 static double suck_double()
278 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
279 memcpy((u1*) (&d), buffer, 8);
281 suck_nbytes((u1*) (&d), 8);
284 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
290 /************************** function suck_init *********************************
292 called once at startup, sets the searchpath for the classfiles
294 *******************************************************************************/
296 void suck_init(char *cpath)
303 /************************** function suck_start ********************************
305 returns true if classbuffer is already loaded or a file for the
306 specified class has succussfully been read in. All directories of
307 the searchpath are used to find the classfile (<classname>.class).
308 Returns false if no classfile is found and writes an error message.
310 *******************************************************************************/
312 bool suck_start(utf *classname)
315 #define MAXFILENAME 1000 /* maximum length of a filename */
317 char filename[MAXFILENAME+10]; /* room for '.class' */
318 char *pathpos; /* position in searchpath */
319 char c, *utf_ptr; /* pointer to the next utf8-character */
321 int filenamelen, err;
325 if (classbuffer) /* classbuffer is already valid */
332 /* skip path separator */
334 while (*pathpos == ':')
337 /* extract directory from searchpath */
340 while ((*pathpos) && (*pathpos != ':')) {
341 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
342 filename[filenamelen++] = *(pathpos++);
346 if (filenamelen > 4) {
347 if ( ((filename[filenamelen - 1] == 'p') || (filename[filenamelen - 1] == 'P')) &
348 ((filename[filenamelen - 2] == 'i') || (filename[filenamelen - 2] == 'I')) &
349 ((filename[filenamelen - 3] == 'z') || (filename[filenamelen - 3] == 'Z')) ) {
356 filename[filenamelen++] = '\0';
357 if (uf == 0) uf = unzOpen(filename);
359 utf_ptr = classname->text;
361 while (utf_ptr < utf_end(classname)) {
362 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
364 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
366 filename[filenamelen++] = c;
368 strcpy(filename + filenamelen, ".class");
369 if (cacao_locate(uf,classname) == UNZ_OK) {
370 unz_file_info file_info;
371 log_text("Class found in zip file");
372 if (unzGetCurrentFileInfo(uf, &file_info, filename,
373 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
374 if (unzOpenCurrentFile(uf) == UNZ_OK) {
375 classbuffer_size = file_info.uncompressed_size;
376 classbuffer = MNEW(u1, classbuffer_size);
377 classbuf_pos = classbuffer - 1;
378 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
379 if (unzReadCurrentFile(uf, classbuffer, classbuffer_size) == classbuffer_size) {
380 unzCloseCurrentFile(uf);
383 MFREE(classbuffer, u1, classbuffer_size);
384 log_text("Error while unzipping");
386 } else log_text("Error while opening file in archive");
387 } else log_text("Error while retrieving fileinfo");
389 unzCloseCurrentFile(uf);
394 filename[filenamelen++] = '/';
396 /* add classname to filename */
398 utf_ptr = classname->text;
399 while (utf_ptr < utf_end(classname)) {
400 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
402 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
404 filename[filenamelen++] = c;
409 strcpy(filename + filenamelen, ".class");
411 classfile = fopen(filename, "r");
412 if (classfile) { /* file exists */
414 /* determine size of classfile */
416 /* dolog("File: %s",filename); */
418 err = stat(filename, &buffer);
420 if (!err) { /* read classfile data */
421 classbuffer_size = buffer.st_size;
422 classbuffer = MNEW(u1, classbuffer_size);
423 classbuf_pos = classbuffer - 1;
424 fread(classbuffer, 1, classbuffer_size, classfile);
432 dolog("Warning: Can not open class file '%s'", filename);
439 /************************** function suck_stop *********************************
441 frees memory for buffer with classfile data.
442 Caution: this function may only be called if buffer has been allocated
443 by suck_start with reading a file
445 *******************************************************************************/
449 /* determine amount of classdata not retrieved by suck-operations */
451 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
453 if (classdata_left > 0) {
455 dolog("There are %d access bytes at end of classfile",
462 MFREE(classbuffer, u1, classbuffer_size);
467 /******************************************************************************/
468 /******************* Some support functions ***********************************/
469 /******************************************************************************/
473 void fprintflags (FILE *fp, u2 f)
475 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
476 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
477 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
478 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
479 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
480 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
481 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
482 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
483 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
484 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
485 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
488 /********** internal function: printflags (only for debugging) ***************/
489 void printflags (u2 f)
491 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
492 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
493 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
494 if ( f & ACC_STATIC ) printf (" STATIC");
495 if ( f & ACC_FINAL ) printf (" FINAL");
496 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
497 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
498 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
499 if ( f & ACC_NATIVE ) printf (" NATIVE");
500 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
501 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
505 /************************* Function: skipattribute *****************************
507 skips a (1) 'attribute' structure in the class file
509 *******************************************************************************/
511 static void skipattribute ()
519 /********************** Function: skipattributebody ****************************
521 skips an attribute after the 16 bit reference to attribute_name has already
524 *******************************************************************************/
526 static void skipattributebody ()
533 /************************* Function: skipattributes ****************************
535 skips num attribute structures
537 *******************************************************************************/
539 static void skipattributes (u4 num)
542 for (i = 0; i < num; i++)
546 /******************** function: innerclass_getconstant ************************
548 like class_getconstant, but if cptags is ZERO null is returned
550 *******************************************************************************/
552 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
554 /* invalid position in constantpool */
555 if (pos >= c->cpcount)
556 panic ("Attempt to access constant outside range");
558 /* constantpool entry of type 0 */
562 /* check type of constantpool entry */
563 if (c->cptags[pos] != ctype) {
564 error ("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
565 (int) ctype, (int) c->cptags[pos] );
568 return c->cpinfos[pos];
571 /************************ function: attribute_load ****************************
573 read attributes from classfile
575 *******************************************************************************/
577 static void attribute_load (u4 num, classinfo *c)
581 for (i = 0; i < num; i++) {
582 /* retrieve attribute name */
583 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
585 if ( aname == utf_innerclasses) {
586 /* innerclasses attribute */
588 /* skip attribute length */
590 /* number of records */
591 c->innerclasscount = suck_u2();
592 /* allocate memory for innerclass structure */
593 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
595 for (j=0;j<c->innerclasscount;j++) {
597 /* The innerclass structure contains a class with an encoded name,
598 its defining scope, its simple name and a bitmask of the access flags.
599 If an inner class is not a member, its outer_class is NULL,
600 if a class is anonymous, its name is NULL. */
602 innerclassinfo *info = c->innerclass + j;
604 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
605 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
606 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
607 info->flags = suck_u2 (); /* access_flags bitmask */
610 /* unknown attribute */
611 skipattributebody ();
616 /******************* function: checkfielddescriptor ****************************
618 checks whether a field-descriptor is valid and aborts otherwise
619 all referenced classes are inserted into the list of unloaded classes
621 *******************************************************************************/
623 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
625 class_from_descriptor(utf_ptr,end_pos,NULL,
627 | CLASSLOAD_NULLPRIMITIVE
629 | CLASSLOAD_CHECKEND);
631 char *tstart; /* pointer to start of classname */
633 char *start = utf_ptr;
635 switch (*utf_ptr++) {
649 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
650 panic ("Ill formed descriptor");
654 panic ("Ill formed descriptor");
657 /* exceeding characters */
658 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
663 /******************* function checkmethoddescriptor ****************************
665 checks whether a method-descriptor is valid and aborts otherwise.
666 All referenced classes are inserted into the list of unloaded classes.
668 *******************************************************************************/
670 static void checkmethoddescriptor (utf *d)
672 char *utf_ptr = d->text; /* current position in utf text */
673 char *end_pos = utf_end(d); /* points behind utf string */
675 /* method descriptor must start with parenthesis */
676 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
678 /* check arguments */
679 while (utf_ptr != end_pos && *utf_ptr != ')') {
680 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
682 | CLASSLOAD_NULLPRIMITIVE
686 if (utf_ptr == end_pos) panic("Missing return type in method descriptor");
687 utf_ptr++; /* skip ')' */
689 class_from_descriptor(utf_ptr,end_pos,NULL,
691 | CLASSLOAD_NULLPRIMITIVE
692 | CLASSLOAD_CHECKEND);
695 /* XXX check length */
696 /* check arguments */
697 while ((c = *utf_ptr++) != ')') {
714 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
715 panic ("Ill formed method descriptor");
719 panic ("Ill formed methodtype-descriptor");
723 /* check returntype */
725 /* returntype void */
726 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
729 /* treat as field-descriptor */
730 checkfielddescriptor (utf_ptr,end_pos);
734 /***************** Function: print_arraydescriptor ****************************
736 Debugging helper for displaying an arraydescriptor
738 *******************************************************************************/
741 print_arraydescriptor(FILE *file,arraydescriptor *desc)
744 fprintf(file,"<NULL>");
749 if (desc->componentvftbl) {
750 if (desc->componentvftbl->class)
751 utf_fprint(file,desc->componentvftbl->class->name);
753 fprintf(file,"<no classinfo>");
759 if (desc->elementvftbl) {
760 if (desc->elementvftbl->class)
761 utf_fprint(file,desc->elementvftbl->class->name);
763 fprintf(file,"<no classinfo>");
767 fprintf(file,",%d,%d,%d,%d}",desc->arraytype,desc->dimension,
768 desc->dataoffset,desc->componentsize);
771 /******************************************************************************/
772 /************************** Functions for fields ****************************/
773 /******************************************************************************/
776 /************************ Function: field_load *********************************
778 Load everything about a class field from the class file and fill a
779 'fieldinfo' structure. For static fields, space in the data segment is
782 *******************************************************************************/
784 static void field_load (fieldinfo *f, classinfo *c)
789 f -> flags = suck_u2 (); /* ACC flags */
790 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
791 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
792 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
793 f -> offset = 0; /* offset from start of object */
797 case TYPE_INT: f->value.i = 0; break;
798 case TYPE_FLOAT: f->value.f = 0.0; break;
799 case TYPE_DOUBLE: f->value.d = 0.0; break;
800 case TYPE_ADDRESS: f->value.a = NULL;
801 heap_addreference (&(f->value.a)); /* make global reference (GC) */
805 f->value.l = 0; break;
807 f->value.l.low = 0; f->value.l.high = 0; break;
811 /* read attributes */
813 for (i=0; i<attrnum; i++) {
817 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
819 if ( aname != utf_constantvalue ) {
820 /* unknown attribute */
821 skipattributebody ();
824 /* constant value attribute */
826 /* skip attribute length */
828 /* index of value in constantpool */
831 /* initialize field with value from constantpool */
834 constant_integer *ci =
835 class_getconstant(c, pindex, CONSTANT_Integer);
836 f->value.i = ci -> value;
842 class_getconstant(c, pindex, CONSTANT_Long);
844 f->value.l = cl -> value;
850 class_getconstant(c, pindex, CONSTANT_Float);
852 f->value.f = cf->value;
857 constant_double *cd =
858 class_getconstant(c, pindex, CONSTANT_Double);
860 f->value.d = cd->value;
865 utf *u = class_getconstant(c, pindex, CONSTANT_String);
866 /* create javastring from compressed utf8-string */
867 f->value.a = literalstring_new(u);
872 log_text ("Invalid Constant - Type");
881 /********************** function: field_free **********************************/
883 static void field_free (fieldinfo *f)
889 /**************** Function: field_display (debugging only) ********************/
891 void field_display (fieldinfo *f)
894 printflags (f -> flags);
896 utf_display (f -> name);
898 utf_display (f -> descriptor);
899 printf (" offset: %ld\n", (long int) (f -> offset) );
903 /******************************************************************************/
904 /************************* Functions for methods ******************************/
905 /******************************************************************************/
908 /*********************** Function: method_load *********************************
910 Loads a method from the class file and fills an existing 'methodinfo'
911 structure. For native methods, the function pointer field is set to the
912 real function pointer, for JavaVM methods a pointer to the compiler is used
915 *******************************************************************************/
917 static void method_load (methodinfo *m, classinfo *c)
927 m -> flags = suck_u2 ();
928 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
929 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
930 checkmethoddescriptor(m->descriptor);
933 m -> exceptiontable = NULL;
934 m -> entrypoint = NULL;
936 m -> stubroutine = NULL;
937 m -> methodUsed = NOTUSED;
938 m -> monoPoly = MONO;
940 m -> subRedefsUsed = 0;
944 if (! (m->flags & ACC_NATIVE) ) {
945 m -> stubroutine = createcompilerstub (m);
949 functionptr f = native_findfunction
950 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
952 m -> stubroutine = createnativestub (f, m);
958 for (i=0; i<attrnum; i++) {
961 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
963 if ( aname != utf_code) {
964 skipattributebody ();
967 if (m -> jcode) panic ("Two code-attributes for one method!");
970 m -> maxstack = suck_u2();
971 m -> maxlocals = suck_u2();
972 m -> jcodelength = suck_u4();
973 m -> jcode = MNEW (u1, m->jcodelength);
974 suck_nbytes (m->jcode, m->jcodelength);
975 m -> exceptiontablelength = suck_u2 ();
976 m -> exceptiontable =
977 MNEW (exceptiontable, m->exceptiontablelength);
980 count_vmcode_len += m->jcodelength + 18;
981 count_extable_len += 8 * m->exceptiontablelength;
984 for (e=0; e < m->exceptiontablelength; e++) {
986 m -> exceptiontable[e].startpc = suck_u2();
987 m -> exceptiontable[e].endpc = suck_u2();
988 m -> exceptiontable[e].handlerpc = suck_u2();
991 if (!idx) m -> exceptiontable[e].catchtype = NULL;
993 m -> exceptiontable[e].catchtype =
994 class_getconstant (c, idx, CONSTANT_Class);
998 skipattributes ( suck_u2() );
1005 /********************* Function: method_free ***********************************
1007 frees all memory that was allocated for this method
1009 *******************************************************************************/
1011 static void method_free (methodinfo *m)
1013 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1014 if (m->exceptiontable)
1015 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1016 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1017 if (m->stubroutine) {
1018 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1019 else removecompilerstub (m->stubroutine);
1024 /************** Function: method_display (debugging only) **************/
1026 void method_display (methodinfo *m)
1029 printflags (m -> flags);
1031 utf_display (m -> name);
1033 utf_display (m -> descriptor);
1038 /******************** Function: method_canoverwrite ****************************
1040 Check if m and old are identical with respect to type and name. This means
1041 that old can be overwritten with m.
1043 *******************************************************************************/
1045 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1047 if (m->name != old->name) return false;
1048 if (m->descriptor != old->descriptor) return false;
1049 if (m->flags & ACC_STATIC) return false;
1056 /******************************************************************************/
1057 /************************ Functions for class *********************************/
1058 /******************************************************************************/
1061 /******************** function:: class_getconstant ******************************
1063 retrieves the value at position 'pos' of the constantpool of a class
1064 if the type of the value is other than 'ctype' the system is stopped
1066 *******************************************************************************/
1068 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1070 /* invalid position in constantpool */
1071 if (pos >= c->cpcount)
1072 panic ("Attempt to access constant outside range");
1074 /* check type of constantpool entry */
1076 if (c->cptags[pos] != ctype) {
1077 class_showconstantpool(c);
1078 error ("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1079 (int) ctype, (int) c->cptags[pos] );
1082 return c->cpinfos[pos];
1086 /********************* Function: class_constanttype ****************************
1088 Determines the type of a class entry in the ConstantPool
1090 *******************************************************************************/
1092 u4 class_constanttype (classinfo *c, u4 pos)
1094 if (pos >= c->cpcount)
1095 panic ("Attempt to access constant outside range");
1096 return c->cptags[pos];
1100 /******************** function: class_loadcpool ********************************
1102 loads the constantpool of a class,
1103 the entries are transformed into a simpler format
1104 by resolving references
1105 (a detailed overview of the compact structures can be found in global.h)
1107 *******************************************************************************/
1109 static void class_loadcpool (classinfo *c)
1112 /* The following structures are used to save information which cannot be
1113 processed during the first pass. After the complete constantpool has
1114 been traversed the references can be resolved.
1115 (only in specific order) */
1117 /* CONSTANT_Class_info entries */
1118 typedef struct forward_class {
1119 struct forward_class *next;
1124 /* CONSTANT_String */
1125 typedef struct forward_string {
1126 struct forward_string *next;
1131 /* CONSTANT_NameAndType */
1132 typedef struct forward_nameandtype {
1133 struct forward_nameandtype *next;
1137 } forward_nameandtype;
1139 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1140 typedef struct forward_fieldmethint {
1141 struct forward_fieldmethint *next;
1145 u2 nameandtype_index;
1146 } forward_fieldmethint;
1150 long int dumpsize = dump_size ();
1152 forward_class *forward_classes = NULL;
1153 forward_string *forward_strings = NULL;
1154 forward_nameandtype *forward_nameandtypes = NULL;
1155 forward_fieldmethint *forward_fieldmethints = NULL;
1157 /* number of entries in the constant_pool table */
1158 u4 cpcount = c -> cpcount = suck_u2();
1159 /* allocate memory */
1160 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1161 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1164 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1167 /* initialize constantpool */
1168 for (idx=0; idx<cpcount; idx++) {
1169 cptags[idx] = CONSTANT_UNUSED;
1170 cpinfos[idx] = NULL;
1174 /******* first pass *******/
1175 /* entries which cannot be resolved now are written into
1176 temporary structures and traversed again later */
1179 while (idx < cpcount) {
1180 /* get constant type */
1184 case CONSTANT_Class: {
1185 forward_class *nfc = DNEW(forward_class);
1187 nfc -> next = forward_classes;
1188 forward_classes = nfc;
1190 nfc -> thisindex = idx;
1191 /* reference to CONSTANT_NameAndType */
1192 nfc -> name_index = suck_u2 ();
1198 case CONSTANT_Fieldref:
1199 case CONSTANT_Methodref:
1200 case CONSTANT_InterfaceMethodref: {
1201 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1203 nff -> next = forward_fieldmethints;
1204 forward_fieldmethints = nff;
1206 nff -> thisindex = idx;
1209 /* class or interface type that contains the declaration of the field or method */
1210 nff -> class_index = suck_u2 ();
1211 /* name and descriptor of the field or method */
1212 nff -> nameandtype_index = suck_u2 ();
1218 case CONSTANT_String: {
1219 forward_string *nfs = DNEW (forward_string);
1221 nfs -> next = forward_strings;
1222 forward_strings = nfs;
1224 nfs -> thisindex = idx;
1225 /* reference to CONSTANT_Utf8_info with string characters */
1226 nfs -> string_index = suck_u2 ();
1232 case CONSTANT_NameAndType: {
1233 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1235 nfn -> next = forward_nameandtypes;
1236 forward_nameandtypes = nfn;
1238 nfn -> thisindex = idx;
1239 /* reference to CONSTANT_Utf8_info containing simple name */
1240 nfn -> name_index = suck_u2 ();
1241 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1242 nfn -> sig_index = suck_u2 ();
1248 case CONSTANT_Integer: {
1249 constant_integer *ci = NEW (constant_integer);
1252 count_const_pool_len += sizeof(constant_integer);
1255 ci -> value = suck_s4 ();
1256 cptags [idx] = CONSTANT_Integer;
1263 case CONSTANT_Float: {
1264 constant_float *cf = NEW (constant_float);
1267 count_const_pool_len += sizeof(constant_float);
1270 cf -> value = suck_float ();
1271 cptags [idx] = CONSTANT_Float;
1277 case CONSTANT_Long: {
1278 constant_long *cl = NEW(constant_long);
1281 count_const_pool_len += sizeof(constant_long);
1284 cl -> value = suck_s8 ();
1285 cptags [idx] = CONSTANT_Long;
1291 case CONSTANT_Double: {
1292 constant_double *cd = NEW(constant_double);
1295 count_const_pool_len += sizeof(constant_double);
1298 cd -> value = suck_double ();
1299 cptags [idx] = CONSTANT_Double;
1305 case CONSTANT_Utf8: {
1307 /* number of bytes in the bytes array (not string-length) */
1308 u4 length = suck_u2();
1309 cptags [idx] = CONSTANT_Utf8;
1310 /* validate the string */
1311 ASSERT_LEFT(length);
1312 if (!is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1313 panic("Invalid UTF-8 string");
1314 /* insert utf-string into the utf-symboltable */
1315 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1316 /* skip bytes of the string */
1317 skip_nbytes(length);
1323 error ("Unkown constant type: %d",(int) t);
1331 /* resolve entries in temporary structures */
1333 while (forward_classes) {
1335 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1337 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1338 /* retrieve class from class-table */
1339 cpinfos [forward_classes -> thisindex] = class_new (name);
1341 forward_classes = forward_classes -> next;
1345 while (forward_strings) {
1347 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1349 log_text("forward_string:");
1350 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1352 log_text("\n------------------"); */
1353 /* resolve utf-string */
1354 cptags [forward_strings -> thisindex] = CONSTANT_String;
1355 cpinfos [forward_strings -> thisindex] = text;
1357 forward_strings = forward_strings -> next;
1360 while (forward_nameandtypes) {
1361 constant_nameandtype *cn = NEW (constant_nameandtype);
1364 count_const_pool_len += sizeof(constant_nameandtype);
1367 /* resolve simple name and descriptor */
1368 cn -> name = class_getconstant
1369 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1370 cn -> descriptor = class_getconstant
1371 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1373 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1374 cpinfos [forward_nameandtypes -> thisindex] = cn;
1376 forward_nameandtypes = forward_nameandtypes -> next;
1380 while (forward_fieldmethints) {
1381 constant_nameandtype *nat;
1382 constant_FMIref *fmi = NEW (constant_FMIref);
1385 count_const_pool_len += sizeof(constant_FMIref);
1387 /* resolve simple name and descriptor */
1388 nat = class_getconstant
1389 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1392 log_text("trying to resolve:");
1393 log_text(nat->name->text);
1394 switch(forward_fieldmethints ->tag) {
1395 case CONSTANT_Fieldref:
1396 log_text("CONSTANT_Fieldref");
1398 case CONSTANT_InterfaceMethodref:
1399 log_text("CONSTANT_InterfaceMethodref");
1401 case CONSTANT_Methodref:
1402 log_text("CONSTANT_Methodref");
1406 fmi -> class = class_getconstant
1407 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1408 fmi -> name = nat -> name;
1409 fmi -> descriptor = nat -> descriptor;
1411 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1412 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1414 switch (forward_fieldmethints -> tag) {
1415 case CONSTANT_Fieldref: /* check validity of descriptor */
1416 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1418 case CONSTANT_InterfaceMethodref:
1419 case CONSTANT_Methodref: /* check validity of descriptor */
1420 /* XXX check special names (<init>) */
1421 checkmethoddescriptor (fmi->descriptor);
1425 forward_fieldmethints = forward_fieldmethints -> next;
1429 /* class_showconstantpool(c); */
1431 dump_release (dumpsize);
1435 /********************** Function: class_load ***********************************
1437 Loads everything interesting about a class from the class file. The
1438 'classinfo' structure must have been allocated previously.
1440 The super class and the interfaces implemented by this class need not be
1441 loaded. The link is set later by the function 'class_link'.
1443 The loaded class is removed from the list 'unloadedclasses' and added to
1444 the list 'unlinkedclasses'.
1446 *******************************************************************************/
1448 static int class_load(classinfo *c)
1454 count_class_loads++;
1457 /* output for debugging purposes */
1459 char logtext[MAXLOGTEXT];
1460 sprintf(logtext, "Loading class: ");
1461 utf_sprint(logtext+strlen(logtext), c->name);
1465 /* load classdata, throw exception on error */
1467 if (!suck_start(c->name)) {
1468 throw_classnotfoundexception2(c->name);
1472 /* check signature */
1473 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1477 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1478 error ("File version %d.%d is not supported",
1479 (int) ma, (int) mi);
1482 class_loadcpool (c);
1484 c->erroneous_state=0;
1485 c->initializing_thread=0;
1487 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1488 c -> impldBy = NULL;
1491 c -> flags = suck_u2 ();
1492 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1497 /* retrieve superclass */
1498 if ( (i = suck_u2 () ) ) {
1499 c -> super = class_getconstant (c, i, CONSTANT_Class);
1505 /* retrieve interfaces */
1506 c -> interfacescount = suck_u2 ();
1507 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1508 for (i=0; i < c -> interfacescount; i++) {
1509 c -> interfaces [i] =
1510 class_getconstant (c, suck_u2(), CONSTANT_Class);
1514 c -> fieldscount = suck_u2 ();
1515 /* utf_display(c->name);
1516 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1518 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1519 for (i=0; i < c -> fieldscount; i++) {
1520 field_load (&(c->fields[i]), c);
1524 c -> methodscount = suck_u2 ();
1525 c -> methods = MNEW (methodinfo, c -> methodscount);
1526 for (i=0; i < c -> methodscount; i++) {
1527 method_load (&(c -> methods [i]), c);
1531 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1532 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1533 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1536 /* load variable-length attribute structures */
1537 attribute_load (suck_u2(), c);
1542 /* remove class from list of unloaded classes and
1543 add to list of unlinked classes */
1544 list_remove (&unloadedclasses, c);
1545 list_addlast (&unlinkedclasses, c);
1552 /************** internal Function: class_highestinterface ***********************
1554 Used by the function class_link to determine the amount of memory needed
1555 for the interface table.
1557 *******************************************************************************/
1559 static s4 class_highestinterface (classinfo *c)
1564 if ( ! (c->flags & ACC_INTERFACE) ) {
1565 char logtext[MAXLOGTEXT];
1566 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1567 utf_sprint (logtext+strlen(logtext), c->name);
1572 for (i=0; i<c->interfacescount; i++) {
1573 s4 h2 = class_highestinterface (c->interfaces[i]);
1580 /* class_addinterface **********************************************************
1582 Is needed by class_link for adding a VTBL to a class. All interfaces
1583 implemented by ic are added as well.
1585 *******************************************************************************/
1587 static void class_addinterface (classinfo *c, classinfo *ic)
1591 vftbl *vftbl = c->vftbl;
1593 if (i >= vftbl->interfacetablelength)
1594 panic ("Inernal error: interfacetable overflow");
1595 if (vftbl->interfacetable[-i])
1598 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1599 vftbl->interfacevftbllength[i] = 1;
1600 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1601 vftbl->interfacetable[-i][0] = NULL;
1604 vftbl->interfacevftbllength[i] = ic->methodscount;
1605 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1608 count_vftbl_len += sizeof(methodptr) *
1609 (ic->methodscount + (ic->methodscount == 0));
1612 for (j=0; j<ic->methodscount; j++) {
1615 for (m = 0; m < sc->methodscount; m++) {
1616 methodinfo *mi = &(sc->methods[m]);
1617 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1618 vftbl->interfacetable[-i][j] =
1619 vftbl->table[mi->vftblindex];
1629 for (j = 0; j < ic->interfacescount; j++)
1630 class_addinterface(c, ic->interfaces[j]);
1634 /******************* Function: class_new_array *********************************
1636 This function is called by class_new to setup an array class.
1638 *******************************************************************************/
1641 class_new_array(classinfo *c)
1643 classinfo *comp = NULL;
1647 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1649 /* Array classes are not loaded from classfiles. */
1650 list_remove (&unloadedclasses, c);
1652 /* Check array class name */
1653 namelen = c->name->blength;
1654 if (namelen < 2 || c->name->text[0] != '[')
1655 panic("Invalid array class name.");
1657 /* Check the component type */
1658 switch (c->name->text[1]) {
1660 /* c is an array of arrays. We have to create the component class. */
1661 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1665 /* c is an array of objects. */
1666 if (namelen < 4 || c->name->text[namelen-1] != ';')
1667 panic("Invalid array class name.");
1668 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1672 /* Setup the array class */
1673 c->super = class_java_lang_Object;
1674 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1676 c->interfacescount = 2;
1677 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1678 c->interfaces[0] = class_java_lang_Cloneable;
1679 c->interfaces[1] = class_java_io_Serializable;
1681 c->methodscount = 1;
1682 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1685 memset(clone,0,sizeof(methodinfo));
1686 clone->flags = ACC_PUBLIC; /* XXX protected? */
1687 clone->name = utf_new_char("clone");
1688 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1690 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1691 clone->monoPoly = MONO; /* XXX should be poly? */
1693 /* XXX: field: length? */
1695 /* The array class has to be linked */
1696 list_addlast(&unlinkedclasses,c);
1699 * Array classes which are created after the other classes have been
1700 * loaded and linked are linked explicitely.
1705 loader_load(c->name); /* XXX handle errors */
1708 /****************** Function: class_link_array *********************************
1710 This function is called by class_link to create the
1711 arraydescriptor for an array class.
1713 This function returns NULL if the array cannot be linked because
1714 the component type has not been linked yet.
1716 *******************************************************************************/
1720 class_link_array(classinfo *c)
1722 classinfo *comp = NULL;
1723 int namelen = c->name->blength;
1724 arraydescriptor *desc;
1727 /* Check the component type */
1728 switch (c->name->text[1]) {
1730 /* c is an array of arrays. */
1731 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1732 if (!comp) panic("Could not find component array class.");
1736 /* c is an array of objects. */
1737 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1738 if (!comp) panic("Could not find component class.");
1742 /* If the component type has not been linked return NULL */
1743 if (comp && !comp->linked)
1746 /* Allocate the arraydescriptor */
1747 desc = NEW(arraydescriptor);
1750 /* c is an array of references */
1751 desc->arraytype = ARRAYTYPE_OBJECT;
1752 desc->componentsize = sizeof(void*);
1753 desc->dataoffset = OFFSET(java_objectarray,data);
1755 compvftbl = comp->vftbl;
1757 panic("Component class has no vftbl.");
1758 desc->componentvftbl = compvftbl;
1760 if (compvftbl->arraydesc) {
1761 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1762 desc->dimension = compvftbl->arraydesc->dimension + 1;
1763 desc->elementtype = compvftbl->arraydesc->elementtype;
1766 desc->elementvftbl = compvftbl;
1767 desc->dimension = 1;
1768 desc->elementtype = ARRAYTYPE_OBJECT;
1772 /* c is an array of a primitive type */
1773 switch (c->name->text[1]) {
1774 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1775 desc->dataoffset = OFFSET(java_booleanarray,data);
1776 desc->componentsize = sizeof(u1); break;
1777 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1778 desc->dataoffset = OFFSET(java_bytearray,data);
1779 desc->componentsize = sizeof(u1); break;
1780 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1781 desc->dataoffset = OFFSET(java_chararray,data);
1782 desc->componentsize = sizeof(u2); break;
1783 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1784 desc->dataoffset = OFFSET(java_doublearray,data);
1785 desc->componentsize = sizeof(double); break;
1786 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1787 desc->dataoffset = OFFSET(java_floatarray,data);
1788 desc->componentsize = sizeof(float); break;
1789 case 'I': desc->arraytype = ARRAYTYPE_INT;
1790 desc->dataoffset = OFFSET(java_intarray,data);
1791 desc->componentsize = sizeof(s4); break;
1792 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1793 desc->dataoffset = OFFSET(java_longarray,data);
1794 desc->componentsize = sizeof(s8); break;
1795 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1796 desc->dataoffset = OFFSET(java_shortarray,data);
1797 desc->componentsize = sizeof(s2); break;
1799 panic("Invalid array class name");
1802 desc->componentvftbl = NULL;
1803 desc->elementvftbl = NULL;
1804 desc->dimension = 1;
1805 desc->elementtype = desc->arraytype;
1811 /********************** Function: class_link ***********************************
1813 Tries to link a class. The super class and every implemented interface must
1814 already have been linked. The function calculates the length in bytes that
1815 an instance of this class requires as well as the VTBL for methods and
1818 If the class can be linked, it is removed from the list 'unlinkedclasses'
1819 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1822 Attention: If cyclical class definitions are encountered, the program gets
1823 into an infinite loop (we'll have to work that out)
1825 *******************************************************************************/
1827 void class_link(classinfo *c)
1829 s4 supervftbllength; /* vftbllegnth of super class */
1830 s4 vftbllength; /* vftbllength of current class */
1831 s4 interfacetablelength; /* interface table length */
1832 classinfo *super = c->super; /* super class */
1833 classinfo *ic, *c2; /* intermediate class variables */
1834 vftbl *v; /* vftbl of current class */
1835 s4 i; /* interface/method/field counter */
1836 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1839 /* check if all superclasses are already linked, if not put c at end of
1840 unlinked list and return. Additionally initialize class fields. */
1842 /* check interfaces */
1844 for (i = 0; i < c->interfacescount; i++) {
1845 ic = c->interfaces[i];
1847 list_remove(&unlinkedclasses, c);
1848 list_addlast(&unlinkedclasses, c);
1853 /* check super class */
1855 if (super == NULL) { /* class java.long.Object */
1857 c->classUsed = USED; /* Object class is always used CO-RT*/
1858 c -> impldBy = NULL;
1859 c->instancesize = sizeof(java_objectheader);
1861 vftbllength = supervftbllength = 0;
1863 c->finalizer = NULL;
1866 if (!super->linked) {
1867 list_remove(&unlinkedclasses, c);
1868 list_addlast(&unlinkedclasses, c);
1872 /* handle array classes */
1873 if (c->name->text[0] == '[')
1874 if ((arraydesc = class_link_array(c)) == NULL) {
1875 list_remove(&unlinkedclasses, c);
1876 list_addlast(&unlinkedclasses, c);
1880 if (c->flags & ACC_INTERFACE)
1881 c->index = interfaceindex++;
1883 c->index = super->index + 1;
1885 c->instancesize = super->instancesize;
1887 vftbllength = supervftbllength = super->vftbl->vftbllength;
1889 c->finalizer = super->finalizer;
1894 char logtext[MAXLOGTEXT];
1895 sprintf (logtext, "Linking Class: ");
1896 utf_sprint (logtext+strlen(logtext), c->name );
1900 /* compute vftbl length */
1902 for (i = 0; i < c->methodscount; i++) {
1903 methodinfo *m = &(c->methods[i]);
1905 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1906 classinfo *sc = super;
1909 for (j = 0; j < sc->methodscount; j++) {
1910 if (method_canoverwrite(m, &(sc->methods[j]))) {
1911 m->vftblindex = sc->methods[j].vftblindex;
1912 goto foundvftblindex;
1917 m->vftblindex = (vftbllength++);
1923 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1926 /* compute interfacetable length */
1928 interfacetablelength = 0;
1931 for (i = 0; i < c2->interfacescount; i++) {
1932 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1933 if (h > interfacetablelength)
1934 interfacetablelength = h;
1939 /* allocate virtual function table */
1941 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1942 (vftbllength - 1) + sizeof(methodptr*) *
1943 (interfacetablelength - (interfacetablelength > 0)));
1944 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1945 (interfacetablelength > 1));
1946 c->header.vftbl = c->vftbl = v;
1948 v->vftbllength = vftbllength;
1949 v->interfacetablelength = interfacetablelength;
1950 v->arraydesc = arraydesc;
1952 /* store interface index in vftbl */
1953 if (c->flags & ACC_INTERFACE)
1954 v->baseval = -(c->index);
1956 /* copy virtual function table of super class */
1958 for (i = 0; i < supervftbllength; i++)
1959 v->table[i] = super->vftbl->table[i];
1961 /* add method stubs into virtual function table */
1963 for (i = 0; i < c->methodscount; i++) {
1964 methodinfo *m = &(c->methods[i]);
1965 if (!(m->flags & ACC_STATIC)) {
1966 v->table[m->vftblindex] = m->stubroutine;
1970 /* compute instance size and offset of each field */
1972 for (i = 0; i < c->fieldscount; i++) {
1974 fieldinfo *f = &(c->fields[i]);
1976 if (!(f->flags & ACC_STATIC) ) {
1977 dsize = desc_typesize (f->descriptor);
1978 c->instancesize = ALIGN (c->instancesize, dsize);
1979 f->offset = c->instancesize;
1980 c->instancesize += dsize;
1984 /* initialize interfacetable and interfacevftbllength */
1986 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1989 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1992 for (i = 0; i < interfacetablelength; i++) {
1993 v->interfacevftbllength[i] = 0;
1994 v->interfacetable[-i] = NULL;
1997 /* add interfaces */
1999 for (c2 = c; c2 != NULL; c2 = c2->super)
2000 for (i = 0; i < c2->interfacescount; i++) {
2001 class_addinterface (c, c2->interfaces[i]);
2004 /* add finalizer method (not for java.lang.Object) */
2006 if (super != NULL) {
2008 static utf *finame = NULL;
2009 static utf *fidesc = NULL;
2012 finame = utf_finalize;
2014 fidesc = utf_fidesc;
2016 fi = class_findmethod (c, finame, fidesc);
2018 if (!(fi->flags & ACC_STATIC)) {
2028 list_remove (&unlinkedclasses, c);
2029 list_addlast (&linkedclasses, c);
2034 /******************* Function: class_freepool **********************************
2036 Frees all resources used by this classes Constant Pool.
2038 *******************************************************************************/
2040 static void class_freecpool (classinfo *c)
2046 for (idx=0; idx < c->cpcount; idx++) {
2047 tag = c->cptags[idx];
2048 info = c->cpinfos[idx];
2052 case CONSTANT_Fieldref:
2053 case CONSTANT_Methodref:
2054 case CONSTANT_InterfaceMethodref:
2055 FREE (info, constant_FMIref);
2057 case CONSTANT_Integer:
2058 FREE (info, constant_integer);
2060 case CONSTANT_Float:
2061 FREE (info, constant_float);
2064 FREE (info, constant_long);
2066 case CONSTANT_Double:
2067 FREE (info, constant_double);
2069 case CONSTANT_NameAndType:
2070 FREE (info, constant_nameandtype);
2076 MFREE (c -> cptags, u1, c -> cpcount);
2077 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2081 /*********************** Function: class_free **********************************
2083 Frees all resources used by the class.
2085 *******************************************************************************/
2087 static void class_free (classinfo *c)
2092 class_freecpool (c);
2094 MFREE (c->interfaces, classinfo*, c->interfacescount);
2096 for (i = 0; i < c->fieldscount; i++)
2097 field_free(&(c->fields[i]));
2099 for (i = 0; i < c->methodscount; i++)
2100 method_free(&(c->methods[i]));
2101 MFREE (c->methods, methodinfo, c->methodscount);
2103 if ((v = c->vftbl) != NULL) {
2105 mem_free(v->arraydesc,sizeof(arraydescriptor));
2107 for (i = 0; i < v->interfacetablelength; i++) {
2108 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2110 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2112 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2113 sizeof(methodptr*) * (v->interfacetablelength -
2114 (v->interfacetablelength > 0));
2115 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2116 (v->interfacetablelength > 1));
2120 if (c->innerclasscount)
2121 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2123 /* if (c->classvftbl)
2124 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2126 FREE (c, classinfo);
2129 /************************* Function: class_findfield ***************************
2131 Searches a 'classinfo' structure for a field having the given name and
2134 *******************************************************************************/
2137 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2142 for (i = 0; i < c->fieldscount; i++) {
2143 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2144 return &(c->fields[i]);
2147 panic ("Can not find field given in CONSTANT_Fieldref");
2152 /************************* Function: class_findmethod **************************
2154 Searches a 'classinfo' structure for a method having the given name and
2155 type and returns the index in the class info structure.
2156 If type is NULL, it is ignored.
2158 *******************************************************************************/
2160 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2163 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2165 int buffer_len, pos;
2167 #ifdef JOWENN_DEBUG1
2170 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2172 buffer = MNEW(char, buffer_len);
2174 strcpy(buffer, "class_findmethod: method:");
2175 utf_sprint(buffer+strlen(buffer), name);
2176 strcpy(buffer+strlen(buffer), ", desc: ");
2177 utf_sprint(buffer+strlen(buffer), desc);
2178 strcpy(buffer+strlen(buffer), ", classname: ");
2179 utf_sprint(buffer+strlen(buffer), c->name);
2183 MFREE(buffer, char, buffer_len);
2185 for (i = 0; i < c->methodscount; i++) {
2186 #ifdef JOWENN_DEBUG2
2188 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2190 buffer = MNEW(char, buffer_len);
2192 strcpy(buffer, "class_findmethod: comparing to method:");
2193 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2194 strcpy(buffer+strlen(buffer), ", desc: ");
2195 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2199 MFREE(buffer, char, buffer_len);
2203 if ((c->methods[i].name == name) && ((desc == NULL) ||
2204 (c->methods[i].descriptor == desc)))
2207 #ifdef JOWENN_DEBUG2
2208 class_showconstantpool(c);
2209 log_text("class_findmethod: returning NULL");
2216 /************************* Function: class_findmethod **************************
2218 Searches a 'classinfo' structure for a method having the given name and
2220 If type is NULL, it is ignored.
2222 *******************************************************************************/
2224 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2228 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2230 int buffer_len, pos;
2232 #ifdef JOWENN_DEBUG1
2235 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2237 buffer = MNEW(char, buffer_len);
2239 strcpy(buffer, "class_findmethod: method:");
2240 utf_sprint(buffer+strlen(buffer), name);
2241 strcpy(buffer+strlen(buffer), ", desc: ");
2242 utf_sprint(buffer+strlen(buffer), desc);
2243 strcpy(buffer+strlen(buffer), ", classname: ");
2244 utf_sprint(buffer+strlen(buffer), c->name);
2248 MFREE(buffer, char, buffer_len);
2250 for (i = 0; i < c->methodscount; i++) {
2251 #ifdef JOWENN_DEBUG2
2253 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2255 buffer = MNEW(char, buffer_len);
2257 strcpy(buffer, "class_findmethod: comparing to method:");
2258 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2259 strcpy(buffer+strlen(buffer), ", desc: ");
2260 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2264 MFREE(buffer, char, buffer_len);
2268 if ((c->methods[i].name == name) && ((desc == NULL) ||
2269 (c->methods[i].descriptor == desc)))
2270 return &(c->methods[i]);
2272 #ifdef JOWENN_DEBUG2
2273 class_showconstantpool(c);
2274 log_text("class_findmethod: returning NULL");
2278 s4 idx=class_findmethodIndex(c,name,desc);
2279 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2280 if (idx==-1) return NULL;
2281 return &(c->methods[idx]);
2285 /*********************** Function: class_fetchmethod **************************
2287 like class_findmethod, but aborts with an error if the method is not found
2289 *******************************************************************************/
2291 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2294 mi = class_findmethod(c,name,desc);
2296 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2297 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2298 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2299 panic("Method not found");
2304 /************************* Function: class_findmethod_approx ******************
2306 like class_findmethod but ignores the return value when comparing the
2309 *******************************************************************************/
2311 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2315 for (i = 0; i < c->methodscount; i++)
2316 if (c->methods[i].name == name) {
2317 utf *meth_descr = c->methods[i].descriptor;
2321 return &(c->methods[i]);
2323 if (desc->blength <= meth_descr->blength) {
2324 /* current position in utf text */
2325 char *desc_utf_ptr = desc->text;
2326 char *meth_utf_ptr = meth_descr->text;
2327 /* points behind utf strings */
2328 char *desc_end = utf_end(desc);
2329 char *meth_end = utf_end(meth_descr);
2332 /* compare argument types */
2333 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2335 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2336 break; /* no match */
2339 return &(c->methods[i]); /* all parameter types equal */
2347 /***************** Function: class_resolvemethod_approx ***********************
2349 Searches a class and every super class for a method (without paying
2350 attention to the return value)
2352 *******************************************************************************/
2354 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2357 /* search for method (ignore returntype) */
2358 methodinfo *m = class_findmethod_approx (c, name, desc);
2361 /* search superclass */
2368 /************************* Function: class_resolvemethod ***********************
2370 Searches a class and every super class for a method.
2372 *******************************************************************************/
2374 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2377 methodinfo *m = class_findmethod(c, name, desc);
2379 /* search superclass */
2387 /************************* Function: class_issubclass **************************
2389 Checks if sub is a descendant of super.
2391 *******************************************************************************/
2393 bool class_issubclass(classinfo *sub, classinfo *super)
2396 if (!sub) return false;
2397 if (sub==super) return true;
2404 /****************** Initialization function for classes ******************
2406 In Java, every class can have a static initialization function. This
2407 function has to be called BEFORE calling other methods or accessing static
2410 *******************************************************************************/
2413 extern int blockInts;
2416 void class_init(classinfo *c)
2419 java_objectheader *exceptionptr;
2424 if (!makeinitializations)
2428 c -> initialized = true;
2433 count_class_inits++;
2437 class_init (c->super);
2438 for (i=0; i < c->interfacescount; i++)
2439 class_init(c->interfaces[i]); /* real */
2441 m = class_findmethod (c, utf_clinit, utf_fidesc);
2444 char logtext[MAXLOGTEXT];
2445 sprintf (logtext, "Class ");
2446 utf_sprint (logtext+strlen(logtext), c->name);
2447 sprintf (logtext+strlen(logtext), " has no initializer");
2450 /* goto callinitialize;*/
2454 if (! (m->flags & ACC_STATIC))
2455 panic ("Class initializer is not static!");
2458 char logtext[MAXLOGTEXT];
2459 sprintf (logtext, "Starting initializer for class: ");
2460 utf_sprint (logtext+strlen(logtext), c->name);
2469 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2472 assert(blockInts == 0);
2477 printf ("#### Initializer of ");
2478 utf_display (c->name);
2479 printf (" has thrown: ");
2480 utf_display (exceptionptr->vftbl->class->name);
2486 char logtext[MAXLOGTEXT];
2487 sprintf (logtext, "Finished initializer for class: ");
2488 utf_sprint (logtext+strlen(logtext), c->name);
2491 if (c->name == utf_systemclass) {
2492 /* class java.lang.System requires explicit initialization */
2495 printf ("#### Initializing class System");
2497 /* find initializing method */
2498 m = class_findmethod (c,
2499 utf_initsystemclass,
2503 /* no method found */
2504 /* printf("initializeSystemClass failed"); */
2512 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2515 assert(blockInts == 0);
2520 printf ("#### initializeSystemClass has thrown: ");
2521 utf_display (exceptionptr->vftbl->class->name);
2532 /********* Function: find_class_method_constant *********/
2533 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2538 for (i=0; i<c->cpcount; i++) {
2540 e = c -> cpinfos [i];
2543 switch (c -> cptags [i]) {
2544 case CONSTANT_Methodref:
2546 constant_FMIref *fmi = e;
2547 if ( (fmi->class->name == c1)
2548 && (fmi->name == m1)
2549 && (fmi->descriptor == d1)) {
2556 case CONSTANT_InterfaceMethodref:
2558 constant_FMIref *fmi = e;
2559 if ( (fmi->class->name == c1)
2560 && (fmi->name == m1)
2561 && (fmi->descriptor == d1)) {
2575 void class_showconstanti(classinfo *c, int ii)
2581 printf ("#%d: ", (int) i);
2583 switch (c->cptags [i]) {
2584 case CONSTANT_Class:
2585 printf("Classreference -> ");
2586 utf_display(((classinfo*)e)->name);
2589 case CONSTANT_Fieldref:
2590 printf("Fieldref -> "); goto displayFMIi;
2591 case CONSTANT_Methodref:
2592 printf("Methodref -> "); goto displayFMIi;
2593 case CONSTANT_InterfaceMethodref:
2594 printf("InterfaceMethod -> "); goto displayFMIi;
2597 constant_FMIref *fmi = e;
2598 utf_display(fmi->class->name);
2600 utf_display(fmi->name);
2602 utf_display(fmi->descriptor);
2606 case CONSTANT_String:
2607 printf("String -> ");
2610 case CONSTANT_Integer:
2611 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2613 case CONSTANT_Float:
2614 printf("Float -> %f", ((constant_float*)e)->value);
2616 case CONSTANT_Double:
2617 printf("Double -> %f", ((constant_double*)e)->value);
2621 u8 v = ((constant_long*)e)->value;
2623 printf("Long -> %ld", (long int) v);
2625 printf("Long -> HI: %ld, LO: %ld\n",
2626 (long int) v.high, (long int) v.low);
2630 case CONSTANT_NameAndType:
2632 constant_nameandtype *cnt = e;
2633 printf("NameAndType: ");
2634 utf_display(cnt->name);
2636 utf_display(cnt->descriptor);
2644 panic("Invalid type of ConstantPool-Entry");
2651 void class_showconstantpool (classinfo *c)
2656 printf ("---- dump of constant pool ----\n");
2658 for (i=0; i<c->cpcount; i++) {
2659 printf ("#%d: ", (int) i);
2661 e = c -> cpinfos [i];
2664 switch (c -> cptags [i]) {
2665 case CONSTANT_Class:
2666 printf ("Classreference -> ");
2667 utf_display ( ((classinfo*)e) -> name );
2670 case CONSTANT_Fieldref:
2671 printf ("Fieldref -> "); goto displayFMI;
2672 case CONSTANT_Methodref:
2673 printf ("Methodref -> "); goto displayFMI;
2674 case CONSTANT_InterfaceMethodref:
2675 printf ("InterfaceMethod -> "); goto displayFMI;
2678 constant_FMIref *fmi = e;
2679 utf_display ( fmi->class->name );
2681 utf_display ( fmi->name);
2683 utf_display ( fmi->descriptor );
2687 case CONSTANT_String:
2688 printf ("String -> ");
2691 case CONSTANT_Integer:
2692 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2694 case CONSTANT_Float:
2695 printf ("Float -> %f", ((constant_float*)e) -> value);
2697 case CONSTANT_Double:
2698 printf ("Double -> %f", ((constant_double*)e) -> value);
2702 u8 v = ((constant_long*)e) -> value;
2704 printf ("Long -> %ld", (long int) v);
2706 printf ("Long -> HI: %ld, LO: %ld\n",
2707 (long int) v.high, (long int) v.low);
2711 case CONSTANT_NameAndType:
2713 constant_nameandtype *cnt = e;
2714 printf ("NameAndType: ");
2715 utf_display (cnt->name);
2717 utf_display (cnt->descriptor);
2721 printf ("Utf8 -> ");
2725 panic ("Invalid type of ConstantPool-Entry");
2735 /********** Function: class_showmethods (debugging only) *************/
2737 void class_showmethods (classinfo *c)
2741 printf ("--------- Fields and Methods ----------------\n");
2742 printf ("Flags: "); printflags (c->flags); printf ("\n");
2744 printf ("This: "); utf_display (c->name); printf ("\n");
2746 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2748 printf ("Index: %d\n", c->index);
2750 printf ("interfaces:\n");
2751 for (i=0; i < c-> interfacescount; i++) {
2753 utf_display (c -> interfaces[i] -> name);
2754 printf (" (%d)\n", c->interfaces[i] -> index);
2757 printf ("fields:\n");
2758 for (i=0; i < c -> fieldscount; i++) {
2759 field_display (&(c -> fields[i]));
2762 printf ("methods:\n");
2763 for (i=0; i < c -> methodscount; i++) {
2764 methodinfo *m = &(c->methods[i]);
2765 if ( !(m->flags & ACC_STATIC))
2766 printf ("vftblindex: %d ", m->vftblindex);
2768 method_display ( m );
2772 printf ("Virtual function table:\n");
2773 for (i=0; i<c->vftbl->vftbllength; i++) {
2774 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2781 /******************************************************************************/
2782 /******************* General functions for the class loader *******************/
2783 /******************************************************************************/
2785 /********************* Function: loader_load ***********************************
2787 Loads and links the class desired class and each class and interface
2789 Returns: a pointer to this class
2791 *******************************************************************************/
2793 static int loader_load_running = 0;
2795 classinfo *loader_load (utf *topname)
2799 long int starttime=0,stoptime=0;
2800 classinfo *notlinkable;
2803 /* avoid recursive calls */
2804 if (loader_load_running)
2805 return class_new(topname);
2806 loader_load_running++;
2808 intsDisable(); /* schani */
2811 starttime = getcputime();
2813 top = class_new (topname);
2816 while ( (c = list_first(&unloadedclasses)) ) {
2817 if (!class_load (c)) {
2818 if (linkverbose) dolog("Failed to load class");
2819 list_remove (&unloadedclasses, c);
2825 if (linkverbose) dolog("Linking...");
2826 /* XXX added a hack to break infinite linking loops. A better
2827 * linking algorithm would be nice. -Edwin */
2829 while ( (c = list_first(&unlinkedclasses)) ) {
2834 else if (notlinkable == c) {
2835 /* We tried to link this class for the second time and
2836 * no other classes were linked in between, so we are
2839 if (linkverbose) dolog("Cannot resolve linking dependencies");
2842 throw_linkageerror2(c->name);
2849 if (linkverbose) dolog("Linking done.");
2852 loader_compute_subclasses();
2855 if (getloadingtime) {
2856 stoptime = getcputime();
2857 loadingtime += (stoptime-starttime);
2861 loader_load_running--;
2863 /* check if a former loader_load call tried to load/link the class and failed.
2864 This is needed because the class didn't appear in the undloadclasses or unlinkedclasses list during this class; */
2867 if (linkverbose) dolog("Failed to load class (former call)");
2868 throw_classnotfoundexception2(top->name);
2870 } else if (!top->linked) {
2871 if (linkverbose) dolog("Failed to link class (former call)");
2872 throw_linkageerror2(top->name);
2877 intsRestore(); /* schani */
2879 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
2884 /****************** Function: loader_load_sysclass ****************************
2886 Loads and links the class desired class and each class and interface
2889 The pointer to the classinfo is stored in *top if top != NULL.
2890 The pointer is also returned.
2892 If the class could not be loaded the function aborts with an error.
2894 *******************************************************************************/
2896 classinfo *loader_load_sysclass(classinfo **top,utf *topname)
2900 if ((cls = loader_load(topname)) == NULL) {
2901 log_plain("Could not important system class: ");
2902 log_plain_utf(topname);
2904 panic("Could not load important system class");
2907 if (top) *top = cls;
2912 /**************** function: create_primitive_classes ***************************
2914 create classes representing primitive types
2916 ********************************************************************************/
2919 void create_primitive_classes()
2923 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2924 /* create primitive class */
2925 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2926 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2927 c -> impldBy = NULL;
2929 /* prevent loader from loading primitive class */
2930 list_remove (&unloadedclasses, c);
2932 /* add to unlinked classes */
2933 list_addlast (&unlinkedclasses, c);
2934 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
2937 primitivetype_table[i].class_primitive = c;
2939 /* create class for wrapping the primitive type */
2940 primitivetype_table[i].class_wrap =
2941 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2942 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2943 primitivetype_table[i].class_wrap -> impldBy = NULL;
2945 /* create the primitive array class */
2946 if (primitivetype_table[i].arrayname) {
2947 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2948 primitivetype_table[i].arrayclass = c;
2950 if (!c->linked) class_link(c);
2951 primitivetype_table[i].arrayvftbl = c->vftbl;
2956 /**************** function: class_primitive_from_sig ***************************
2958 return the primitive class indicated by the given signature character
2960 If the descriptor does not indicate a valid primitive type the
2961 return value is NULL.
2963 ********************************************************************************/
2965 classinfo *class_primitive_from_sig(char sig)
2968 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2969 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2970 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2971 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2972 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2973 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2974 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2975 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2976 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2981 /****************** function: class_from_descriptor ****************************
2983 return the class indicated by the given descriptor
2985 utf_ptr....first character of descriptor
2986 end_ptr....first character after the end of the string
2987 next.......if non-NULL, *next is set to the first character after
2988 the descriptor. (Undefined if an error occurs.)
2990 mode.......a combination (binary or) of the following flags:
2992 (Flags marked with * are the default settings.)
2994 What to do if a reference type descriptor is parsed successfully:
2996 CLASSLOAD_SKIP...skip it and return something != NULL
2997 * CLASSLOAD_NEW....get classinfo * via class_new
2998 CLASSLOAD_LOAD...get classinfo * via loader_load
3000 How to handle primitive types:
3002 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3003 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3005 How to handle "V" descriptors:
3007 * CLASSLOAD_VOID.....handle it like other primitive types
3008 CLASSLOAD_NOVOID...treat it as an error
3010 How to deal with extra characters after the end of the
3013 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3014 CLASSLOAD_CHECKEND.....treat them as an error
3016 How to deal with errors:
3018 * CLASSLOAD_PANIC....abort execution with an error message
3019 CLASSLOAD_NOPANIC..return NULL on error
3021 ********************************************************************************/
3024 class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
3026 char *start = utf_ptr;
3030 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3032 if (mode & CLASSLOAD_CHECKEND)
3033 error |= (utf_ptr != end_ptr);
3036 if (next) *next = utf_ptr;
3040 if (mode & CLASSLOAD_NOVOID)
3051 return (mode & CLASSLOAD_NULLPRIMITIVE)
3053 : class_primitive_from_sig(*start);
3060 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3061 name = utf_new(start,utf_ptr-start);
3062 return (mode & CLASSLOAD_LOAD)
3063 ? loader_load(name) : class_new(name); /* XXX */
3067 /* An error occurred */
3068 if (mode & CLASSLOAD_NOPANIC)
3071 log_plain("Invalid descriptor at beginning of '");
3072 log_plain_utf(utf_new(start,end_ptr-start));
3076 panic("Invalid descriptor");
3079 /******************* function: type_from_descriptor ****************************
3081 return the basic type indicated by the given descriptor
3083 This function parses a descriptor and returns its basic type as
3084 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3086 cls...if non-NULL the referenced variable is set to the classinfo *
3087 returned by class_from_descriptor.
3089 For documentation of the arguments utf_ptr, end_ptr, next and mode
3090 see class_from_descriptor. The only difference is that
3091 type_from_descriptor always uses CLASSLOAD_PANIC.
3093 ********************************************************************************/
3096 type_from_descriptor(classinfo **cls,char *utf_ptr,char *end_ptr,char **next,int mode)
3099 if (!cls) cls = &mycls;
3100 *cls = class_from_descriptor(utf_ptr,end_ptr,next,mode & (~CLASSLOAD_NOPANIC));
3117 return TYPE_ADDRESS;
3120 /*************** function: create_pseudo_classes *******************************
3122 create pseudo classes used by the typechecker
3124 ********************************************************************************/
3127 create_pseudo_classes()
3129 /* pseudo class for Arraystubs (extends java.lang.Object) */
3131 pseudo_class_Arraystub = class_new( utf_new_char("$ARRAYSTUB$") );
3132 list_remove(&unloadedclasses,pseudo_class_Arraystub);
3134 pseudo_class_Arraystub->super = class_java_lang_Object;
3135 pseudo_class_Arraystub->interfacescount = 2;
3136 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
3137 pseudo_class_Arraystub->interfaces[0] =
3138 class_java_lang_Cloneable;
3139 pseudo_class_Arraystub->interfaces[1] =
3140 class_java_io_Serializable;
3142 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
3143 class_link(pseudo_class_Arraystub);
3145 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3147 /* pseudo class representing the null type */
3149 pseudo_class_Null = class_new( utf_new_char("$NULL$") );
3150 list_remove(&unloadedclasses,pseudo_class_Null);
3152 pseudo_class_Null->super = class_java_lang_Object;
3154 list_addlast(&unlinkedclasses,pseudo_class_Null);
3155 class_link(pseudo_class_Null);
3157 /* pseudo class representing new uninitialized objects */
3159 pseudo_class_New = class_new( utf_new_char("$NEW$") );
3160 list_remove(&unloadedclasses,pseudo_class_New);
3162 pseudo_class_New->super = class_java_lang_Object;
3164 list_addlast(&unlinkedclasses,pseudo_class_New);
3165 class_link(pseudo_class_New);
3168 /********************** Function: loader_init **********************************
3170 Initializes all lists and loads all classes required for the system or the
3173 *******************************************************************************/
3175 void loader_init (u1 * stackbottom)
3180 log_text("Entering loader_init");
3183 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
3184 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
3185 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
3187 /* create utf-symbols for pointer comparison of frequently used strings */
3188 utf_innerclasses = utf_new_char("InnerClasses");
3189 utf_constantvalue = utf_new_char("ConstantValue");
3190 utf_code = utf_new_char("Code");
3191 utf_finalize = utf_new_char("finalize");
3192 utf_fidesc = utf_new_char("()V");
3193 utf_clinit = utf_new_char("<clinit>");
3194 utf_initsystemclass = utf_new_char("initializeSystemClass");
3195 utf_systemclass = utf_new_char("java/lang/System");
3196 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
3197 utf_initialize =utf_new_char("initialize");
3198 utf_initializedesc =utf_new_char("(I)V");
3200 utf_vmclass =utf_new_char("java/lang/VMClass");
3202 /* create some important classes */
3203 /* These classes have to be created now because the classinfo
3204 * pointers are used in the loading code.
3206 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
3207 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
3208 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
3209 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
3211 log_text("loader_init: java/lang/Object");
3212 /* load the classes which were created above */
3213 loader_load_sysclass (NULL,class_java_lang_Object->name);
3215 loader_inited=1; /*JOWENN*/
3217 loader_load_sysclass(&class_java_lang_Throwable,
3218 utf_new_char("java/lang/Throwable") );
3220 log_text("loader_init: loader_load: java/lang/ClassCastException");
3221 loader_load_sysclass(&class_java_lang_ClassCastException,
3222 utf_new_char ("java/lang/ClassCastException") );
3223 loader_load_sysclass(&class_java_lang_NullPointerException,
3224 utf_new_char ("java/lang/NullPointerException") );
3225 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3226 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
3227 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3228 utf_new_char ("java/lang/NegativeArraySizeException") );
3229 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3230 utf_new_char ("java/lang/OutOfMemoryError") );
3231 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3232 utf_new_char ("java/lang/ArrayStoreException") );
3233 loader_load_sysclass(&class_java_lang_ArithmeticException,
3234 utf_new_char ("java/lang/ArithmeticException") );
3235 loader_load_sysclass(&class_java_lang_ThreadDeath,
3236 utf_new_char ("java/lang/ThreadDeath") );/* schani */
3238 /* create classes representing primitive types */
3239 create_primitive_classes();
3241 /* create classes used by the typechecker */
3242 create_pseudo_classes();
3244 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3245 stringtable_update();
3253 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3254 proto_java_lang_ClassCastException =
3255 builtin_new(class_java_lang_ClassCastException);
3256 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3258 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3260 proto_java_lang_NullPointerException =
3261 builtin_new(class_java_lang_NullPointerException);
3262 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3263 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3265 proto_java_lang_ArrayIndexOutOfBoundsException =
3266 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3267 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3269 proto_java_lang_NegativeArraySizeException =
3270 builtin_new(class_java_lang_NegativeArraySizeException);
3271 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3273 proto_java_lang_OutOfMemoryError =
3274 builtin_new(class_java_lang_OutOfMemoryError);
3275 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3277 proto_java_lang_ArithmeticException =
3278 builtin_new(class_java_lang_ArithmeticException);
3279 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3281 proto_java_lang_ArrayStoreException =
3282 builtin_new(class_java_lang_ArrayStoreException);
3283 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3285 proto_java_lang_ThreadDeath = /* schani */
3286 builtin_new(class_java_lang_ThreadDeath);
3287 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3296 /********************* Function: loader_initclasses ****************************
3298 Initializes all loaded but uninitialized classes
3300 *******************************************************************************/
3302 void loader_initclasses ()
3306 intsDisable(); /* schani */
3308 if (makeinitializations) {
3309 c = list_first (&linkedclasses);
3312 c = list_next (&linkedclasses, c);
3316 intsRestore(); /* schani */
3319 static s4 classvalue;
3321 static void loader_compute_class_values (classinfo *c)
3325 c->vftbl->baseval = ++classvalue;
3328 while (subs != NULL) {
3329 loader_compute_class_values(subs);
3330 subs = subs->nextsub;
3332 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3337 for (i = 0; i < c->index; i++)
3339 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3340 utf_display(c->name);
3348 void loader_compute_subclasses ()
3352 intsDisable(); /* schani */
3354 c = list_first (&linkedclasses);
3356 if (!(c->flags & ACC_INTERFACE)) {
3360 c = list_next (&linkedclasses, c);
3363 c = list_first (&linkedclasses);
3365 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3366 c->nextsub = c->super->sub;
3369 c = list_next (&linkedclasses, c);
3372 loader_compute_class_values(class_java_lang_Object);
3374 intsRestore(); /* schani */
3379 /******************** function classloader_buffer ******************************
3381 sets buffer for reading classdata
3383 *******************************************************************************/
3385 void classload_buffer(u1 *buf, int len)
3388 classbuffer_size = len;
3389 classbuf_pos = buf - 1;
3393 /******************** Function: loader_close ***********************************
3397 *******************************************************************************/
3399 void loader_close ()
3403 while ( (c=list_first(&unloadedclasses)) ) {
3404 list_remove (&unloadedclasses,c);
3407 while ( (c=list_first(&unlinkedclasses)) ) {
3408 list_remove (&unlinkedclasses,c);
3411 while ( (c=list_first(&linkedclasses)) ) {
3412 list_remove (&linkedclasses,c);
3419 * These are local overrides for various environment variables in Emacs.
3420 * Please do not remove this and leave it at the end of the file, where
3421 * Emacs will automagically detect them.
3422 * ---------------------------------------------------------------------
3425 * indent-tabs-mode: t