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 726 2003-12-10 15:41:07Z 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 ();
968 if (m -> jcode) panic ("Two code-attributes for one method!");
971 m -> maxstack = suck_u2();
972 m -> maxlocals = suck_u2();
975 panic("bytecode has zero length");
977 panic("bytecode too long");
978 m -> jcodelength = codelen;
979 m -> jcode = MNEW (u1, m->jcodelength);
980 suck_nbytes (m->jcode, m->jcodelength);
981 m -> exceptiontablelength = suck_u2 ();
982 m -> exceptiontable =
983 MNEW (exceptiontable, m->exceptiontablelength);
986 count_vmcode_len += m->jcodelength + 18;
987 count_extable_len += 8 * m->exceptiontablelength;
990 for (e=0; e < m->exceptiontablelength; e++) {
992 m -> exceptiontable[e].startpc = suck_u2();
993 m -> exceptiontable[e].endpc = suck_u2();
994 m -> exceptiontable[e].handlerpc = suck_u2();
997 if (!idx) m -> exceptiontable[e].catchtype = NULL;
999 m -> exceptiontable[e].catchtype =
1000 class_getconstant (c, idx, CONSTANT_Class);
1004 skipattributes ( suck_u2() );
1011 /********************* Function: method_free ***********************************
1013 frees all memory that was allocated for this method
1015 *******************************************************************************/
1017 static void method_free (methodinfo *m)
1019 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1020 if (m->exceptiontable)
1021 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1022 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1023 if (m->stubroutine) {
1024 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1025 else removecompilerstub (m->stubroutine);
1030 /************** Function: method_display (debugging only) **************/
1032 void method_display (methodinfo *m)
1035 printflags (m -> flags);
1037 utf_display (m -> name);
1039 utf_display (m -> descriptor);
1044 /******************** Function: method_canoverwrite ****************************
1046 Check if m and old are identical with respect to type and name. This means
1047 that old can be overwritten with m.
1049 *******************************************************************************/
1051 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1053 if (m->name != old->name) return false;
1054 if (m->descriptor != old->descriptor) return false;
1055 if (m->flags & ACC_STATIC) return false;
1062 /******************************************************************************/
1063 /************************ Functions for class *********************************/
1064 /******************************************************************************/
1067 /******************** function:: class_getconstant ******************************
1069 retrieves the value at position 'pos' of the constantpool of a class
1070 if the type of the value is other than 'ctype' the system is stopped
1072 *******************************************************************************/
1074 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1076 /* invalid position in constantpool */
1077 if (pos >= c->cpcount)
1078 panic ("Attempt to access constant outside range");
1080 /* check type of constantpool entry */
1082 if (c->cptags[pos] != ctype) {
1083 class_showconstantpool(c);
1084 error ("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1085 (int) ctype, (int) c->cptags[pos] );
1088 return c->cpinfos[pos];
1092 /********************* Function: class_constanttype ****************************
1094 Determines the type of a class entry in the ConstantPool
1096 *******************************************************************************/
1098 u4 class_constanttype (classinfo *c, u4 pos)
1100 if (pos >= c->cpcount)
1101 panic ("Attempt to access constant outside range");
1102 return c->cptags[pos];
1106 /******************** function: class_loadcpool ********************************
1108 loads the constantpool of a class,
1109 the entries are transformed into a simpler format
1110 by resolving references
1111 (a detailed overview of the compact structures can be found in global.h)
1113 *******************************************************************************/
1115 static void class_loadcpool (classinfo *c)
1118 /* The following structures are used to save information which cannot be
1119 processed during the first pass. After the complete constantpool has
1120 been traversed the references can be resolved.
1121 (only in specific order) */
1123 /* CONSTANT_Class_info entries */
1124 typedef struct forward_class {
1125 struct forward_class *next;
1130 /* CONSTANT_String */
1131 typedef struct forward_string {
1132 struct forward_string *next;
1137 /* CONSTANT_NameAndType */
1138 typedef struct forward_nameandtype {
1139 struct forward_nameandtype *next;
1143 } forward_nameandtype;
1145 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1146 typedef struct forward_fieldmethint {
1147 struct forward_fieldmethint *next;
1151 u2 nameandtype_index;
1152 } forward_fieldmethint;
1156 long int dumpsize = dump_size ();
1158 forward_class *forward_classes = NULL;
1159 forward_string *forward_strings = NULL;
1160 forward_nameandtype *forward_nameandtypes = NULL;
1161 forward_fieldmethint *forward_fieldmethints = NULL;
1163 /* number of entries in the constant_pool table */
1164 u4 cpcount = c -> cpcount = suck_u2();
1165 /* allocate memory */
1166 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1167 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1170 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1173 /* initialize constantpool */
1174 for (idx=0; idx<cpcount; idx++) {
1175 cptags[idx] = CONSTANT_UNUSED;
1176 cpinfos[idx] = NULL;
1180 /******* first pass *******/
1181 /* entries which cannot be resolved now are written into
1182 temporary structures and traversed again later */
1185 while (idx < cpcount) {
1186 /* get constant type */
1190 case CONSTANT_Class: {
1191 forward_class *nfc = DNEW(forward_class);
1193 nfc -> next = forward_classes;
1194 forward_classes = nfc;
1196 nfc -> thisindex = idx;
1197 /* reference to CONSTANT_NameAndType */
1198 nfc -> name_index = suck_u2 ();
1204 case CONSTANT_Fieldref:
1205 case CONSTANT_Methodref:
1206 case CONSTANT_InterfaceMethodref: {
1207 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1209 nff -> next = forward_fieldmethints;
1210 forward_fieldmethints = nff;
1212 nff -> thisindex = idx;
1215 /* class or interface type that contains the declaration of the field or method */
1216 nff -> class_index = suck_u2 ();
1217 /* name and descriptor of the field or method */
1218 nff -> nameandtype_index = suck_u2 ();
1224 case CONSTANT_String: {
1225 forward_string *nfs = DNEW (forward_string);
1227 nfs -> next = forward_strings;
1228 forward_strings = nfs;
1230 nfs -> thisindex = idx;
1231 /* reference to CONSTANT_Utf8_info with string characters */
1232 nfs -> string_index = suck_u2 ();
1238 case CONSTANT_NameAndType: {
1239 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1241 nfn -> next = forward_nameandtypes;
1242 forward_nameandtypes = nfn;
1244 nfn -> thisindex = idx;
1245 /* reference to CONSTANT_Utf8_info containing simple name */
1246 nfn -> name_index = suck_u2 ();
1247 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1248 nfn -> sig_index = suck_u2 ();
1254 case CONSTANT_Integer: {
1255 constant_integer *ci = NEW (constant_integer);
1258 count_const_pool_len += sizeof(constant_integer);
1261 ci -> value = suck_s4 ();
1262 cptags [idx] = CONSTANT_Integer;
1269 case CONSTANT_Float: {
1270 constant_float *cf = NEW (constant_float);
1273 count_const_pool_len += sizeof(constant_float);
1276 cf -> value = suck_float ();
1277 cptags [idx] = CONSTANT_Float;
1283 case CONSTANT_Long: {
1284 constant_long *cl = NEW(constant_long);
1287 count_const_pool_len += sizeof(constant_long);
1290 cl -> value = suck_s8 ();
1291 cptags [idx] = CONSTANT_Long;
1297 case CONSTANT_Double: {
1298 constant_double *cd = NEW(constant_double);
1301 count_const_pool_len += sizeof(constant_double);
1304 cd -> value = suck_double ();
1305 cptags [idx] = CONSTANT_Double;
1311 case CONSTANT_Utf8: {
1313 /* number of bytes in the bytes array (not string-length) */
1314 u4 length = suck_u2();
1315 cptags [idx] = CONSTANT_Utf8;
1316 /* validate the string */
1317 ASSERT_LEFT(length);
1318 if (!is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1319 panic("Invalid UTF-8 string");
1320 /* insert utf-string into the utf-symboltable */
1321 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1322 /* skip bytes of the string */
1323 skip_nbytes(length);
1329 error ("Unkown constant type: %d",(int) t);
1337 /* resolve entries in temporary structures */
1339 while (forward_classes) {
1341 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1343 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1344 /* retrieve class from class-table */
1345 cpinfos [forward_classes -> thisindex] = class_new (name);
1347 forward_classes = forward_classes -> next;
1351 while (forward_strings) {
1353 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1355 log_text("forward_string:");
1356 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1358 log_text("\n------------------"); */
1359 /* resolve utf-string */
1360 cptags [forward_strings -> thisindex] = CONSTANT_String;
1361 cpinfos [forward_strings -> thisindex] = text;
1363 forward_strings = forward_strings -> next;
1366 while (forward_nameandtypes) {
1367 constant_nameandtype *cn = NEW (constant_nameandtype);
1370 count_const_pool_len += sizeof(constant_nameandtype);
1373 /* resolve simple name and descriptor */
1374 cn -> name = class_getconstant
1375 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1376 cn -> descriptor = class_getconstant
1377 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1379 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1380 cpinfos [forward_nameandtypes -> thisindex] = cn;
1382 forward_nameandtypes = forward_nameandtypes -> next;
1386 while (forward_fieldmethints) {
1387 constant_nameandtype *nat;
1388 constant_FMIref *fmi = NEW (constant_FMIref);
1391 count_const_pool_len += sizeof(constant_FMIref);
1393 /* resolve simple name and descriptor */
1394 nat = class_getconstant
1395 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1398 log_text("trying to resolve:");
1399 log_text(nat->name->text);
1400 switch(forward_fieldmethints ->tag) {
1401 case CONSTANT_Fieldref:
1402 log_text("CONSTANT_Fieldref");
1404 case CONSTANT_InterfaceMethodref:
1405 log_text("CONSTANT_InterfaceMethodref");
1407 case CONSTANT_Methodref:
1408 log_text("CONSTANT_Methodref");
1412 fmi -> class = class_getconstant
1413 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1414 fmi -> name = nat -> name;
1415 fmi -> descriptor = nat -> descriptor;
1417 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1418 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1420 switch (forward_fieldmethints -> tag) {
1421 case CONSTANT_Fieldref: /* check validity of descriptor */
1422 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1424 case CONSTANT_InterfaceMethodref:
1425 case CONSTANT_Methodref: /* check validity of descriptor */
1426 /* XXX check special names (<init>) */
1427 checkmethoddescriptor (fmi->descriptor);
1431 forward_fieldmethints = forward_fieldmethints -> next;
1435 /* class_showconstantpool(c); */
1437 dump_release (dumpsize);
1441 /********************** Function: class_load ***********************************
1443 Loads everything interesting about a class from the class file. The
1444 'classinfo' structure must have been allocated previously.
1446 The super class and the interfaces implemented by this class need not be
1447 loaded. The link is set later by the function 'class_link'.
1449 The loaded class is removed from the list 'unloadedclasses' and added to
1450 the list 'unlinkedclasses'.
1452 *******************************************************************************/
1454 static int class_load(classinfo *c)
1460 count_class_loads++;
1463 /* output for debugging purposes */
1465 char logtext[MAXLOGTEXT];
1466 sprintf(logtext, "Loading class: ");
1467 utf_sprint(logtext+strlen(logtext), c->name);
1471 /* load classdata, throw exception on error */
1473 if (!suck_start(c->name)) {
1474 throw_classnotfoundexception2(c->name);
1478 /* check signature */
1479 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1483 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1484 error ("File version %d.%d is not supported",
1485 (int) ma, (int) mi);
1488 class_loadcpool (c);
1490 c->erroneous_state=0;
1491 c->initializing_thread=0;
1493 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1494 c -> impldBy = NULL;
1497 c -> flags = suck_u2 ();
1498 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1503 /* retrieve superclass */
1504 if ( (i = suck_u2 () ) ) {
1505 c -> super = class_getconstant (c, i, CONSTANT_Class);
1511 /* retrieve interfaces */
1512 c -> interfacescount = suck_u2 ();
1513 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1514 for (i=0; i < c -> interfacescount; i++) {
1515 c -> interfaces [i] =
1516 class_getconstant (c, suck_u2(), CONSTANT_Class);
1520 c -> fieldscount = suck_u2 ();
1521 /* utf_display(c->name);
1522 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1524 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1525 for (i=0; i < c -> fieldscount; i++) {
1526 field_load (&(c->fields[i]), c);
1530 c -> methodscount = suck_u2 ();
1531 c -> methods = MNEW (methodinfo, c -> methodscount);
1532 for (i=0; i < c -> methodscount; i++) {
1533 method_load (&(c -> methods [i]), c);
1537 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1538 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1539 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1542 /* load variable-length attribute structures */
1543 attribute_load (suck_u2(), c);
1548 /* remove class from list of unloaded classes and
1549 add to list of unlinked classes */
1550 list_remove (&unloadedclasses, c);
1551 list_addlast (&unlinkedclasses, c);
1558 /************** internal Function: class_highestinterface ***********************
1560 Used by the function class_link to determine the amount of memory needed
1561 for the interface table.
1563 *******************************************************************************/
1565 static s4 class_highestinterface (classinfo *c)
1570 if ( ! (c->flags & ACC_INTERFACE) ) {
1571 char logtext[MAXLOGTEXT];
1572 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1573 utf_sprint (logtext+strlen(logtext), c->name);
1578 for (i=0; i<c->interfacescount; i++) {
1579 s4 h2 = class_highestinterface (c->interfaces[i]);
1586 /* class_addinterface **********************************************************
1588 Is needed by class_link for adding a VTBL to a class. All interfaces
1589 implemented by ic are added as well.
1591 *******************************************************************************/
1593 static void class_addinterface (classinfo *c, classinfo *ic)
1597 vftbl *vftbl = c->vftbl;
1599 if (i >= vftbl->interfacetablelength)
1600 panic ("Inernal error: interfacetable overflow");
1601 if (vftbl->interfacetable[-i])
1604 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1605 vftbl->interfacevftbllength[i] = 1;
1606 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1607 vftbl->interfacetable[-i][0] = NULL;
1610 vftbl->interfacevftbllength[i] = ic->methodscount;
1611 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1614 count_vftbl_len += sizeof(methodptr) *
1615 (ic->methodscount + (ic->methodscount == 0));
1618 for (j=0; j<ic->methodscount; j++) {
1621 for (m = 0; m < sc->methodscount; m++) {
1622 methodinfo *mi = &(sc->methods[m]);
1623 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1624 vftbl->interfacetable[-i][j] =
1625 vftbl->table[mi->vftblindex];
1635 for (j = 0; j < ic->interfacescount; j++)
1636 class_addinterface(c, ic->interfaces[j]);
1640 /******************* Function: class_new_array *********************************
1642 This function is called by class_new to setup an array class.
1644 *******************************************************************************/
1647 class_new_array(classinfo *c)
1649 classinfo *comp = NULL;
1653 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1655 /* Array classes are not loaded from classfiles. */
1656 list_remove (&unloadedclasses, c);
1658 /* Check array class name */
1659 namelen = c->name->blength;
1660 if (namelen < 2 || c->name->text[0] != '[')
1661 panic("Invalid array class name");
1663 /* Check the component type */
1664 switch (c->name->text[1]) {
1666 /* c is an array of arrays. We have to create the component class. */
1667 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1671 /* c is an array of objects. */
1672 if (namelen < 4 || c->name->text[namelen-1] != ';')
1673 panic("Invalid array class name");
1674 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1678 /* Setup the array class */
1679 c->super = class_java_lang_Object;
1680 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1682 c->interfacescount = 2;
1683 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1684 c->interfaces[0] = class_java_lang_Cloneable;
1685 c->interfaces[1] = class_java_io_Serializable;
1687 c->methodscount = 1;
1688 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1691 memset(clone,0,sizeof(methodinfo));
1692 clone->flags = ACC_PUBLIC; /* XXX protected? */
1693 clone->name = utf_new_char("clone");
1694 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1696 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1697 clone->monoPoly = MONO; /* XXX should be poly? */
1699 /* XXX: field: length? */
1701 /* The array class has to be linked */
1702 list_addlast(&unlinkedclasses,c);
1705 * Array classes which are created after the other classes have been
1706 * loaded and linked are linked explicitely.
1711 loader_load(c->name); /* XXX handle errors */
1714 /****************** Function: class_link_array *********************************
1716 This function is called by class_link to create the
1717 arraydescriptor for an array class.
1719 This function returns NULL if the array cannot be linked because
1720 the component type has not been linked yet.
1722 *******************************************************************************/
1726 class_link_array(classinfo *c)
1728 classinfo *comp = NULL;
1729 int namelen = c->name->blength;
1730 arraydescriptor *desc;
1733 /* Check the component type */
1734 switch (c->name->text[1]) {
1736 /* c is an array of arrays. */
1737 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1738 if (!comp) panic("Could not find component array class.");
1742 /* c is an array of objects. */
1743 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1744 if (!comp) panic("Could not find component class.");
1748 /* If the component type has not been linked return NULL */
1749 if (comp && !comp->linked)
1752 /* Allocate the arraydescriptor */
1753 desc = NEW(arraydescriptor);
1756 /* c is an array of references */
1757 desc->arraytype = ARRAYTYPE_OBJECT;
1758 desc->componentsize = sizeof(void*);
1759 desc->dataoffset = OFFSET(java_objectarray,data);
1761 compvftbl = comp->vftbl;
1763 panic("Component class has no vftbl.");
1764 desc->componentvftbl = compvftbl;
1766 if (compvftbl->arraydesc) {
1767 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1768 desc->dimension = compvftbl->arraydesc->dimension + 1;
1769 desc->elementtype = compvftbl->arraydesc->elementtype;
1772 desc->elementvftbl = compvftbl;
1773 desc->dimension = 1;
1774 desc->elementtype = ARRAYTYPE_OBJECT;
1778 /* c is an array of a primitive type */
1779 switch (c->name->text[1]) {
1780 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1781 desc->dataoffset = OFFSET(java_booleanarray,data);
1782 desc->componentsize = sizeof(u1); break;
1783 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1784 desc->dataoffset = OFFSET(java_bytearray,data);
1785 desc->componentsize = sizeof(u1); break;
1786 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1787 desc->dataoffset = OFFSET(java_chararray,data);
1788 desc->componentsize = sizeof(u2); break;
1789 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1790 desc->dataoffset = OFFSET(java_doublearray,data);
1791 desc->componentsize = sizeof(double); break;
1792 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1793 desc->dataoffset = OFFSET(java_floatarray,data);
1794 desc->componentsize = sizeof(float); break;
1795 case 'I': desc->arraytype = ARRAYTYPE_INT;
1796 desc->dataoffset = OFFSET(java_intarray,data);
1797 desc->componentsize = sizeof(s4); break;
1798 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1799 desc->dataoffset = OFFSET(java_longarray,data);
1800 desc->componentsize = sizeof(s8); break;
1801 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1802 desc->dataoffset = OFFSET(java_shortarray,data);
1803 desc->componentsize = sizeof(s2); break;
1805 panic("Invalid array class name");
1808 desc->componentvftbl = NULL;
1809 desc->elementvftbl = NULL;
1810 desc->dimension = 1;
1811 desc->elementtype = desc->arraytype;
1817 /********************** Function: class_link ***********************************
1819 Tries to link a class. The super class and every implemented interface must
1820 already have been linked. The function calculates the length in bytes that
1821 an instance of this class requires as well as the VTBL for methods and
1824 If the class can be linked, it is removed from the list 'unlinkedclasses'
1825 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1828 Attention: If cyclical class definitions are encountered, the program gets
1829 into an infinite loop (we'll have to work that out)
1831 *******************************************************************************/
1833 void class_link(classinfo *c)
1835 s4 supervftbllength; /* vftbllegnth of super class */
1836 s4 vftbllength; /* vftbllength of current class */
1837 s4 interfacetablelength; /* interface table length */
1838 classinfo *super = c->super; /* super class */
1839 classinfo *ic, *c2; /* intermediate class variables */
1840 vftbl *v; /* vftbl of current class */
1841 s4 i; /* interface/method/field counter */
1842 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1845 /* check if all superclasses are already linked, if not put c at end of
1846 unlinked list and return. Additionally initialize class fields. */
1848 /* check interfaces */
1850 for (i = 0; i < c->interfacescount; i++) {
1851 ic = c->interfaces[i];
1853 list_remove(&unlinkedclasses, c);
1854 list_addlast(&unlinkedclasses, c);
1859 /* check super class */
1861 if (super == NULL) { /* class java.long.Object */
1863 c->classUsed = USED; /* Object class is always used CO-RT*/
1864 c -> impldBy = NULL;
1865 c->instancesize = sizeof(java_objectheader);
1867 vftbllength = supervftbllength = 0;
1869 c->finalizer = NULL;
1872 if (!super->linked) {
1873 list_remove(&unlinkedclasses, c);
1874 list_addlast(&unlinkedclasses, c);
1878 /* handle array classes */
1879 if (c->name->text[0] == '[')
1880 if ((arraydesc = class_link_array(c)) == NULL) {
1881 list_remove(&unlinkedclasses, c);
1882 list_addlast(&unlinkedclasses, c);
1886 if (c->flags & ACC_INTERFACE)
1887 c->index = interfaceindex++;
1889 c->index = super->index + 1;
1891 c->instancesize = super->instancesize;
1893 vftbllength = supervftbllength = super->vftbl->vftbllength;
1895 c->finalizer = super->finalizer;
1900 char logtext[MAXLOGTEXT];
1901 sprintf (logtext, "Linking Class: ");
1902 utf_sprint (logtext+strlen(logtext), c->name );
1906 /* compute vftbl length */
1908 for (i = 0; i < c->methodscount; i++) {
1909 methodinfo *m = &(c->methods[i]);
1911 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1912 classinfo *sc = super;
1915 for (j = 0; j < sc->methodscount; j++) {
1916 if (method_canoverwrite(m, &(sc->methods[j]))) {
1917 m->vftblindex = sc->methods[j].vftblindex;
1918 goto foundvftblindex;
1923 m->vftblindex = (vftbllength++);
1929 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1932 /* compute interfacetable length */
1934 interfacetablelength = 0;
1937 for (i = 0; i < c2->interfacescount; i++) {
1938 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1939 if (h > interfacetablelength)
1940 interfacetablelength = h;
1945 /* allocate virtual function table */
1947 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1948 (vftbllength - 1) + sizeof(methodptr*) *
1949 (interfacetablelength - (interfacetablelength > 0)));
1950 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1951 (interfacetablelength > 1));
1952 c->header.vftbl = c->vftbl = v;
1954 v->vftbllength = vftbllength;
1955 v->interfacetablelength = interfacetablelength;
1956 v->arraydesc = arraydesc;
1958 /* store interface index in vftbl */
1959 if (c->flags & ACC_INTERFACE)
1960 v->baseval = -(c->index);
1962 /* copy virtual function table of super class */
1964 for (i = 0; i < supervftbllength; i++)
1965 v->table[i] = super->vftbl->table[i];
1967 /* add method stubs into virtual function table */
1969 for (i = 0; i < c->methodscount; i++) {
1970 methodinfo *m = &(c->methods[i]);
1971 if (!(m->flags & ACC_STATIC)) {
1972 v->table[m->vftblindex] = m->stubroutine;
1976 /* compute instance size and offset of each field */
1978 for (i = 0; i < c->fieldscount; i++) {
1980 fieldinfo *f = &(c->fields[i]);
1982 if (!(f->flags & ACC_STATIC) ) {
1983 dsize = desc_typesize (f->descriptor);
1984 c->instancesize = ALIGN (c->instancesize, dsize);
1985 f->offset = c->instancesize;
1986 c->instancesize += dsize;
1990 /* initialize interfacetable and interfacevftbllength */
1992 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1995 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1998 for (i = 0; i < interfacetablelength; i++) {
1999 v->interfacevftbllength[i] = 0;
2000 v->interfacetable[-i] = NULL;
2003 /* add interfaces */
2005 for (c2 = c; c2 != NULL; c2 = c2->super)
2006 for (i = 0; i < c2->interfacescount; i++) {
2007 class_addinterface (c, c2->interfaces[i]);
2010 /* add finalizer method (not for java.lang.Object) */
2012 if (super != NULL) {
2014 static utf *finame = NULL;
2015 static utf *fidesc = NULL;
2018 finame = utf_finalize;
2020 fidesc = utf_fidesc;
2022 fi = class_findmethod (c, finame, fidesc);
2024 if (!(fi->flags & ACC_STATIC)) {
2034 list_remove (&unlinkedclasses, c);
2035 list_addlast (&linkedclasses, c);
2040 /******************* Function: class_freepool **********************************
2042 Frees all resources used by this classes Constant Pool.
2044 *******************************************************************************/
2046 static void class_freecpool (classinfo *c)
2052 for (idx=0; idx < c->cpcount; idx++) {
2053 tag = c->cptags[idx];
2054 info = c->cpinfos[idx];
2058 case CONSTANT_Fieldref:
2059 case CONSTANT_Methodref:
2060 case CONSTANT_InterfaceMethodref:
2061 FREE (info, constant_FMIref);
2063 case CONSTANT_Integer:
2064 FREE (info, constant_integer);
2066 case CONSTANT_Float:
2067 FREE (info, constant_float);
2070 FREE (info, constant_long);
2072 case CONSTANT_Double:
2073 FREE (info, constant_double);
2075 case CONSTANT_NameAndType:
2076 FREE (info, constant_nameandtype);
2082 MFREE (c -> cptags, u1, c -> cpcount);
2083 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2087 /*********************** Function: class_free **********************************
2089 Frees all resources used by the class.
2091 *******************************************************************************/
2093 static void class_free (classinfo *c)
2098 class_freecpool (c);
2100 MFREE (c->interfaces, classinfo*, c->interfacescount);
2102 for (i = 0; i < c->fieldscount; i++)
2103 field_free(&(c->fields[i]));
2105 for (i = 0; i < c->methodscount; i++)
2106 method_free(&(c->methods[i]));
2107 MFREE (c->methods, methodinfo, c->methodscount);
2109 if ((v = c->vftbl) != NULL) {
2111 mem_free(v->arraydesc,sizeof(arraydescriptor));
2113 for (i = 0; i < v->interfacetablelength; i++) {
2114 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2116 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2118 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2119 sizeof(methodptr*) * (v->interfacetablelength -
2120 (v->interfacetablelength > 0));
2121 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2122 (v->interfacetablelength > 1));
2126 if (c->innerclasscount)
2127 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2129 /* if (c->classvftbl)
2130 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2132 FREE (c, classinfo);
2135 /************************* Function: class_findfield ***************************
2137 Searches a 'classinfo' structure for a field having the given name and
2140 *******************************************************************************/
2143 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2148 for (i = 0; i < c->fieldscount; i++) {
2149 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2150 return &(c->fields[i]);
2153 panic ("Can not find field given in CONSTANT_Fieldref");
2158 /************************* Function: class_findmethod **************************
2160 Searches a 'classinfo' structure for a method having the given name and
2161 type and returns the index in the class info structure.
2162 If type is NULL, it is ignored.
2164 *******************************************************************************/
2166 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2169 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2171 int buffer_len, pos;
2173 #ifdef JOWENN_DEBUG1
2176 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2178 buffer = MNEW(char, buffer_len);
2180 strcpy(buffer, "class_findmethod: method:");
2181 utf_sprint(buffer+strlen(buffer), name);
2182 strcpy(buffer+strlen(buffer), ", desc: ");
2183 utf_sprint(buffer+strlen(buffer), desc);
2184 strcpy(buffer+strlen(buffer), ", classname: ");
2185 utf_sprint(buffer+strlen(buffer), c->name);
2189 MFREE(buffer, char, buffer_len);
2191 for (i = 0; i < c->methodscount; i++) {
2192 #ifdef JOWENN_DEBUG2
2194 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2196 buffer = MNEW(char, buffer_len);
2198 strcpy(buffer, "class_findmethod: comparing to method:");
2199 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2200 strcpy(buffer+strlen(buffer), ", desc: ");
2201 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2205 MFREE(buffer, char, buffer_len);
2209 if ((c->methods[i].name == name) && ((desc == NULL) ||
2210 (c->methods[i].descriptor == desc)))
2213 #ifdef JOWENN_DEBUG2
2214 class_showconstantpool(c);
2215 log_text("class_findmethod: returning NULL");
2222 /************************* Function: class_findmethod **************************
2224 Searches a 'classinfo' structure for a method having the given name and
2226 If type is NULL, it is ignored.
2228 *******************************************************************************/
2230 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2234 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2236 int buffer_len, pos;
2238 #ifdef JOWENN_DEBUG1
2241 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2243 buffer = MNEW(char, buffer_len);
2245 strcpy(buffer, "class_findmethod: method:");
2246 utf_sprint(buffer+strlen(buffer), name);
2247 strcpy(buffer+strlen(buffer), ", desc: ");
2248 utf_sprint(buffer+strlen(buffer), desc);
2249 strcpy(buffer+strlen(buffer), ", classname: ");
2250 utf_sprint(buffer+strlen(buffer), c->name);
2254 MFREE(buffer, char, buffer_len);
2256 for (i = 0; i < c->methodscount; i++) {
2257 #ifdef JOWENN_DEBUG2
2259 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2261 buffer = MNEW(char, buffer_len);
2263 strcpy(buffer, "class_findmethod: comparing to method:");
2264 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2265 strcpy(buffer+strlen(buffer), ", desc: ");
2266 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2270 MFREE(buffer, char, buffer_len);
2274 if ((c->methods[i].name == name) && ((desc == NULL) ||
2275 (c->methods[i].descriptor == desc)))
2276 return &(c->methods[i]);
2278 #ifdef JOWENN_DEBUG2
2279 class_showconstantpool(c);
2280 log_text("class_findmethod: returning NULL");
2284 s4 idx=class_findmethodIndex(c,name,desc);
2285 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2286 if (idx==-1) return NULL;
2287 return &(c->methods[idx]);
2291 /*********************** Function: class_fetchmethod **************************
2293 like class_findmethod, but aborts with an error if the method is not found
2295 *******************************************************************************/
2297 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2300 mi = class_findmethod(c,name,desc);
2302 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2303 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2304 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2305 panic("Method not found");
2310 /************************* Function: class_findmethod_approx ******************
2312 like class_findmethod but ignores the return value when comparing the
2315 *******************************************************************************/
2317 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2321 for (i = 0; i < c->methodscount; i++)
2322 if (c->methods[i].name == name) {
2323 utf *meth_descr = c->methods[i].descriptor;
2327 return &(c->methods[i]);
2329 if (desc->blength <= meth_descr->blength) {
2330 /* current position in utf text */
2331 char *desc_utf_ptr = desc->text;
2332 char *meth_utf_ptr = meth_descr->text;
2333 /* points behind utf strings */
2334 char *desc_end = utf_end(desc);
2335 char *meth_end = utf_end(meth_descr);
2338 /* compare argument types */
2339 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2341 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2342 break; /* no match */
2345 return &(c->methods[i]); /* all parameter types equal */
2353 /***************** Function: class_resolvemethod_approx ***********************
2355 Searches a class and every super class for a method (without paying
2356 attention to the return value)
2358 *******************************************************************************/
2360 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2363 /* search for method (ignore returntype) */
2364 methodinfo *m = class_findmethod_approx (c, name, desc);
2367 /* search superclass */
2374 /************************* Function: class_resolvemethod ***********************
2376 Searches a class and every super class for a method.
2378 *******************************************************************************/
2380 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2383 methodinfo *m = class_findmethod(c, name, desc);
2385 /* search superclass */
2393 /************************* Function: class_issubclass **************************
2395 Checks if sub is a descendant of super.
2397 *******************************************************************************/
2399 bool class_issubclass(classinfo *sub, classinfo *super)
2402 if (!sub) return false;
2403 if (sub==super) return true;
2410 /****************** Initialization function for classes ******************
2412 In Java, every class can have a static initialization function. This
2413 function has to be called BEFORE calling other methods or accessing static
2416 *******************************************************************************/
2419 extern int blockInts;
2422 void class_init(classinfo *c)
2425 java_objectheader *exceptionptr;
2430 if (!makeinitializations)
2434 c -> initialized = true;
2439 count_class_inits++;
2443 class_init (c->super);
2444 for (i=0; i < c->interfacescount; i++)
2445 class_init(c->interfaces[i]); /* real */
2447 m = class_findmethod (c, utf_clinit, utf_fidesc);
2450 char logtext[MAXLOGTEXT];
2451 sprintf (logtext, "Class ");
2452 utf_sprint (logtext+strlen(logtext), c->name);
2453 sprintf (logtext+strlen(logtext), " has no initializer");
2456 /* goto callinitialize;*/
2460 if (! (m->flags & ACC_STATIC))
2461 panic ("Class initializer is not static!");
2464 char logtext[MAXLOGTEXT];
2465 sprintf (logtext, "Starting initializer for class: ");
2466 utf_sprint (logtext+strlen(logtext), c->name);
2475 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2478 assert(blockInts == 0);
2483 printf ("#### Initializer of ");
2484 utf_display (c->name);
2485 printf (" has thrown: ");
2486 utf_display (exceptionptr->vftbl->class->name);
2492 char logtext[MAXLOGTEXT];
2493 sprintf (logtext, "Finished initializer for class: ");
2494 utf_sprint (logtext+strlen(logtext), c->name);
2497 if (c->name == utf_systemclass) {
2498 /* class java.lang.System requires explicit initialization */
2501 printf ("#### Initializing class System");
2503 /* find initializing method */
2504 m = class_findmethod (c,
2505 utf_initsystemclass,
2509 /* no method found */
2510 /* printf("initializeSystemClass failed"); */
2518 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2521 assert(blockInts == 0);
2526 printf ("#### initializeSystemClass has thrown: ");
2527 utf_display (exceptionptr->vftbl->class->name);
2538 /********* Function: find_class_method_constant *********/
2539 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2544 for (i=0; i<c->cpcount; i++) {
2546 e = c -> cpinfos [i];
2549 switch (c -> cptags [i]) {
2550 case CONSTANT_Methodref:
2552 constant_FMIref *fmi = e;
2553 if ( (fmi->class->name == c1)
2554 && (fmi->name == m1)
2555 && (fmi->descriptor == d1)) {
2562 case CONSTANT_InterfaceMethodref:
2564 constant_FMIref *fmi = e;
2565 if ( (fmi->class->name == c1)
2566 && (fmi->name == m1)
2567 && (fmi->descriptor == d1)) {
2581 void class_showconstanti(classinfo *c, int ii)
2587 printf ("#%d: ", (int) i);
2589 switch (c->cptags [i]) {
2590 case CONSTANT_Class:
2591 printf("Classreference -> ");
2592 utf_display(((classinfo*)e)->name);
2595 case CONSTANT_Fieldref:
2596 printf("Fieldref -> "); goto displayFMIi;
2597 case CONSTANT_Methodref:
2598 printf("Methodref -> "); goto displayFMIi;
2599 case CONSTANT_InterfaceMethodref:
2600 printf("InterfaceMethod -> "); goto displayFMIi;
2603 constant_FMIref *fmi = e;
2604 utf_display(fmi->class->name);
2606 utf_display(fmi->name);
2608 utf_display(fmi->descriptor);
2612 case CONSTANT_String:
2613 printf("String -> ");
2616 case CONSTANT_Integer:
2617 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2619 case CONSTANT_Float:
2620 printf("Float -> %f", ((constant_float*)e)->value);
2622 case CONSTANT_Double:
2623 printf("Double -> %f", ((constant_double*)e)->value);
2627 u8 v = ((constant_long*)e)->value;
2629 printf("Long -> %ld", (long int) v);
2631 printf("Long -> HI: %ld, LO: %ld\n",
2632 (long int) v.high, (long int) v.low);
2636 case CONSTANT_NameAndType:
2638 constant_nameandtype *cnt = e;
2639 printf("NameAndType: ");
2640 utf_display(cnt->name);
2642 utf_display(cnt->descriptor);
2650 panic("Invalid type of ConstantPool-Entry");
2657 void class_showconstantpool (classinfo *c)
2662 printf ("---- dump of constant pool ----\n");
2664 for (i=0; i<c->cpcount; i++) {
2665 printf ("#%d: ", (int) i);
2667 e = c -> cpinfos [i];
2670 switch (c -> cptags [i]) {
2671 case CONSTANT_Class:
2672 printf ("Classreference -> ");
2673 utf_display ( ((classinfo*)e) -> name );
2676 case CONSTANT_Fieldref:
2677 printf ("Fieldref -> "); goto displayFMI;
2678 case CONSTANT_Methodref:
2679 printf ("Methodref -> "); goto displayFMI;
2680 case CONSTANT_InterfaceMethodref:
2681 printf ("InterfaceMethod -> "); goto displayFMI;
2684 constant_FMIref *fmi = e;
2685 utf_display ( fmi->class->name );
2687 utf_display ( fmi->name);
2689 utf_display ( fmi->descriptor );
2693 case CONSTANT_String:
2694 printf ("String -> ");
2697 case CONSTANT_Integer:
2698 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2700 case CONSTANT_Float:
2701 printf ("Float -> %f", ((constant_float*)e) -> value);
2703 case CONSTANT_Double:
2704 printf ("Double -> %f", ((constant_double*)e) -> value);
2708 u8 v = ((constant_long*)e) -> value;
2710 printf ("Long -> %ld", (long int) v);
2712 printf ("Long -> HI: %ld, LO: %ld\n",
2713 (long int) v.high, (long int) v.low);
2717 case CONSTANT_NameAndType:
2719 constant_nameandtype *cnt = e;
2720 printf ("NameAndType: ");
2721 utf_display (cnt->name);
2723 utf_display (cnt->descriptor);
2727 printf ("Utf8 -> ");
2731 panic ("Invalid type of ConstantPool-Entry");
2741 /********** Function: class_showmethods (debugging only) *************/
2743 void class_showmethods (classinfo *c)
2747 printf ("--------- Fields and Methods ----------------\n");
2748 printf ("Flags: "); printflags (c->flags); printf ("\n");
2750 printf ("This: "); utf_display (c->name); printf ("\n");
2752 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2754 printf ("Index: %d\n", c->index);
2756 printf ("interfaces:\n");
2757 for (i=0; i < c-> interfacescount; i++) {
2759 utf_display (c -> interfaces[i] -> name);
2760 printf (" (%d)\n", c->interfaces[i] -> index);
2763 printf ("fields:\n");
2764 for (i=0; i < c -> fieldscount; i++) {
2765 field_display (&(c -> fields[i]));
2768 printf ("methods:\n");
2769 for (i=0; i < c -> methodscount; i++) {
2770 methodinfo *m = &(c->methods[i]);
2771 if ( !(m->flags & ACC_STATIC))
2772 printf ("vftblindex: %d ", m->vftblindex);
2774 method_display ( m );
2778 printf ("Virtual function table:\n");
2779 for (i=0; i<c->vftbl->vftbllength; i++) {
2780 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2787 /******************************************************************************/
2788 /******************* General functions for the class loader *******************/
2789 /******************************************************************************/
2791 /********************* Function: loader_load ***********************************
2793 Loads and links the class desired class and each class and interface
2795 Returns: a pointer to this class
2797 *******************************************************************************/
2799 static int loader_load_running = 0;
2801 classinfo *loader_load (utf *topname)
2805 long int starttime=0,stoptime=0;
2806 classinfo *notlinkable;
2809 /* avoid recursive calls */
2810 if (loader_load_running)
2811 return class_new(topname);
2812 loader_load_running++;
2814 intsDisable(); /* schani */
2817 starttime = getcputime();
2819 top = class_new (topname);
2822 while ( (c = list_first(&unloadedclasses)) ) {
2823 if (!class_load (c)) {
2824 if (linkverbose) dolog("Failed to load class");
2825 list_remove (&unloadedclasses, c);
2831 if (linkverbose) dolog("Linking...");
2832 /* XXX added a hack to break infinite linking loops. A better
2833 * linking algorithm would be nice. -Edwin */
2835 while ( (c = list_first(&unlinkedclasses)) ) {
2840 else if (notlinkable == c) {
2841 /* We tried to link this class for the second time and
2842 * no other classes were linked in between, so we are
2845 if (linkverbose) dolog("Cannot resolve linking dependencies");
2848 throw_linkageerror2(c->name);
2855 if (linkverbose) dolog("Linking done.");
2858 loader_compute_subclasses();
2861 if (getloadingtime) {
2862 stoptime = getcputime();
2863 loadingtime += (stoptime-starttime);
2867 loader_load_running--;
2869 /* check if a former loader_load call tried to load/link the class and failed.
2870 This is needed because the class didn't appear in the undloadclasses or unlinkedclasses list during this class; */
2873 if (linkverbose) dolog("Failed to load class (former call)");
2874 throw_classnotfoundexception2(top->name);
2876 } else if (!top->linked) {
2877 if (linkverbose) dolog("Failed to link class (former call)");
2878 throw_linkageerror2(top->name);
2883 intsRestore(); /* schani */
2885 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
2890 /****************** Function: loader_load_sysclass ****************************
2892 Loads and links the class desired class and each class and interface
2895 The pointer to the classinfo is stored in *top if top != NULL.
2896 The pointer is also returned.
2898 If the class could not be loaded the function aborts with an error.
2900 *******************************************************************************/
2902 classinfo *loader_load_sysclass(classinfo **top,utf *topname)
2906 if ((cls = loader_load(topname)) == NULL) {
2907 log_plain("Could not important system class: ");
2908 log_plain_utf(topname);
2910 panic("Could not load important system class");
2913 if (top) *top = cls;
2918 /**************** function: create_primitive_classes ***************************
2920 create classes representing primitive types
2922 ********************************************************************************/
2925 void create_primitive_classes()
2929 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2930 /* create primitive class */
2931 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2932 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2933 c -> impldBy = NULL;
2935 /* prevent loader from loading primitive class */
2936 list_remove (&unloadedclasses, c);
2938 /* add to unlinked classes */
2939 list_addlast (&unlinkedclasses, c);
2940 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
2943 primitivetype_table[i].class_primitive = c;
2945 /* create class for wrapping the primitive type */
2946 primitivetype_table[i].class_wrap =
2947 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2948 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2949 primitivetype_table[i].class_wrap -> impldBy = NULL;
2951 /* create the primitive array class */
2952 if (primitivetype_table[i].arrayname) {
2953 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2954 primitivetype_table[i].arrayclass = c;
2956 if (!c->linked) class_link(c);
2957 primitivetype_table[i].arrayvftbl = c->vftbl;
2962 /**************** function: class_primitive_from_sig ***************************
2964 return the primitive class indicated by the given signature character
2966 If the descriptor does not indicate a valid primitive type the
2967 return value is NULL.
2969 ********************************************************************************/
2971 classinfo *class_primitive_from_sig(char sig)
2974 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2975 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2976 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2977 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2978 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2979 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2980 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2981 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2982 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2987 /****************** function: class_from_descriptor ****************************
2989 return the class indicated by the given descriptor
2991 utf_ptr....first character of descriptor
2992 end_ptr....first character after the end of the string
2993 next.......if non-NULL, *next is set to the first character after
2994 the descriptor. (Undefined if an error occurs.)
2996 mode.......a combination (binary or) of the following flags:
2998 (Flags marked with * are the default settings.)
3000 What to do if a reference type descriptor is parsed successfully:
3002 CLASSLOAD_SKIP...skip it and return something != NULL
3003 * CLASSLOAD_NEW....get classinfo * via class_new
3004 CLASSLOAD_LOAD...get classinfo * via loader_load
3006 How to handle primitive types:
3008 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3009 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3011 How to handle "V" descriptors:
3013 * CLASSLOAD_VOID.....handle it like other primitive types
3014 CLASSLOAD_NOVOID...treat it as an error
3016 How to deal with extra characters after the end of the
3019 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3020 CLASSLOAD_CHECKEND.....treat them as an error
3022 How to deal with errors:
3024 * CLASSLOAD_PANIC....abort execution with an error message
3025 CLASSLOAD_NOPANIC..return NULL on error
3027 ********************************************************************************/
3030 class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
3032 char *start = utf_ptr;
3036 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3038 if (mode & CLASSLOAD_CHECKEND)
3039 error |= (utf_ptr != end_ptr);
3042 if (next) *next = utf_ptr;
3046 if (mode & CLASSLOAD_NOVOID)
3057 return (mode & CLASSLOAD_NULLPRIMITIVE)
3059 : class_primitive_from_sig(*start);
3066 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3067 name = utf_new(start,utf_ptr-start);
3068 return (mode & CLASSLOAD_LOAD)
3069 ? loader_load(name) : class_new(name); /* XXX */
3073 /* An error occurred */
3074 if (mode & CLASSLOAD_NOPANIC)
3077 log_plain("Invalid descriptor at beginning of '");
3078 log_plain_utf(utf_new(start,end_ptr-start));
3082 panic("Invalid descriptor");
3085 /******************* function: type_from_descriptor ****************************
3087 return the basic type indicated by the given descriptor
3089 This function parses a descriptor and returns its basic type as
3090 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3092 cls...if non-NULL the referenced variable is set to the classinfo *
3093 returned by class_from_descriptor.
3095 For documentation of the arguments utf_ptr, end_ptr, next and mode
3096 see class_from_descriptor. The only difference is that
3097 type_from_descriptor always uses CLASSLOAD_PANIC.
3099 ********************************************************************************/
3102 type_from_descriptor(classinfo **cls,char *utf_ptr,char *end_ptr,char **next,int mode)
3105 if (!cls) cls = &mycls;
3106 *cls = class_from_descriptor(utf_ptr,end_ptr,next,mode & (~CLASSLOAD_NOPANIC));
3123 return TYPE_ADDRESS;
3126 /*************** function: create_pseudo_classes *******************************
3128 create pseudo classes used by the typechecker
3130 ********************************************************************************/
3133 create_pseudo_classes()
3135 /* pseudo class for Arraystubs (extends java.lang.Object) */
3137 pseudo_class_Arraystub = class_new( utf_new_char("$ARRAYSTUB$") );
3138 list_remove(&unloadedclasses,pseudo_class_Arraystub);
3140 pseudo_class_Arraystub->super = class_java_lang_Object;
3141 pseudo_class_Arraystub->interfacescount = 2;
3142 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
3143 pseudo_class_Arraystub->interfaces[0] =
3144 class_java_lang_Cloneable;
3145 pseudo_class_Arraystub->interfaces[1] =
3146 class_java_io_Serializable;
3148 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
3149 class_link(pseudo_class_Arraystub);
3151 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3153 /* pseudo class representing the null type */
3155 pseudo_class_Null = class_new( utf_new_char("$NULL$") );
3156 list_remove(&unloadedclasses,pseudo_class_Null);
3158 pseudo_class_Null->super = class_java_lang_Object;
3160 list_addlast(&unlinkedclasses,pseudo_class_Null);
3161 class_link(pseudo_class_Null);
3163 /* pseudo class representing new uninitialized objects */
3165 pseudo_class_New = class_new( utf_new_char("$NEW$") );
3166 list_remove(&unloadedclasses,pseudo_class_New);
3168 pseudo_class_New->super = class_java_lang_Object;
3170 list_addlast(&unlinkedclasses,pseudo_class_New);
3171 class_link(pseudo_class_New);
3174 /********************** Function: loader_init **********************************
3176 Initializes all lists and loads all classes required for the system or the
3179 *******************************************************************************/
3181 void loader_init (u1 * stackbottom)
3186 log_text("Entering loader_init");
3189 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
3190 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
3191 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
3193 /* create utf-symbols for pointer comparison of frequently used strings */
3194 utf_innerclasses = utf_new_char("InnerClasses");
3195 utf_constantvalue = utf_new_char("ConstantValue");
3196 utf_code = utf_new_char("Code");
3197 utf_finalize = utf_new_char("finalize");
3198 utf_fidesc = utf_new_char("()V");
3199 utf_clinit = utf_new_char("<clinit>");
3200 utf_initsystemclass = utf_new_char("initializeSystemClass");
3201 utf_systemclass = utf_new_char("java/lang/System");
3202 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
3203 utf_initialize =utf_new_char("initialize");
3204 utf_initializedesc =utf_new_char("(I)V");
3206 utf_vmclass =utf_new_char("java/lang/VMClass");
3208 /* create some important classes */
3209 /* These classes have to be created now because the classinfo
3210 * pointers are used in the loading code.
3212 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
3213 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
3214 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
3215 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
3217 log_text("loader_init: java/lang/Object");
3218 /* load the classes which were created above */
3219 loader_load_sysclass (NULL,class_java_lang_Object->name);
3221 loader_inited=1; /*JOWENN*/
3223 loader_load_sysclass(&class_java_lang_Throwable,
3224 utf_new_char("java/lang/Throwable") );
3226 log_text("loader_init: loader_load: java/lang/ClassCastException");
3227 loader_load_sysclass(&class_java_lang_ClassCastException,
3228 utf_new_char ("java/lang/ClassCastException") );
3229 loader_load_sysclass(&class_java_lang_NullPointerException,
3230 utf_new_char ("java/lang/NullPointerException") );
3231 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3232 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
3233 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3234 utf_new_char ("java/lang/NegativeArraySizeException") );
3235 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3236 utf_new_char ("java/lang/OutOfMemoryError") );
3237 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3238 utf_new_char ("java/lang/ArrayStoreException") );
3239 loader_load_sysclass(&class_java_lang_ArithmeticException,
3240 utf_new_char ("java/lang/ArithmeticException") );
3241 loader_load_sysclass(&class_java_lang_ThreadDeath,
3242 utf_new_char ("java/lang/ThreadDeath") );/* schani */
3244 /* create classes representing primitive types */
3245 create_primitive_classes();
3247 /* create classes used by the typechecker */
3248 create_pseudo_classes();
3250 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3251 stringtable_update();
3259 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3260 proto_java_lang_ClassCastException =
3261 builtin_new(class_java_lang_ClassCastException);
3262 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3264 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3266 proto_java_lang_NullPointerException =
3267 builtin_new(class_java_lang_NullPointerException);
3268 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3269 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3271 proto_java_lang_ArrayIndexOutOfBoundsException =
3272 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3273 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3275 proto_java_lang_NegativeArraySizeException =
3276 builtin_new(class_java_lang_NegativeArraySizeException);
3277 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3279 proto_java_lang_OutOfMemoryError =
3280 builtin_new(class_java_lang_OutOfMemoryError);
3281 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3283 proto_java_lang_ArithmeticException =
3284 builtin_new(class_java_lang_ArithmeticException);
3285 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3287 proto_java_lang_ArrayStoreException =
3288 builtin_new(class_java_lang_ArrayStoreException);
3289 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3291 proto_java_lang_ThreadDeath = /* schani */
3292 builtin_new(class_java_lang_ThreadDeath);
3293 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3302 /********************* Function: loader_initclasses ****************************
3304 Initializes all loaded but uninitialized classes
3306 *******************************************************************************/
3308 void loader_initclasses ()
3312 intsDisable(); /* schani */
3314 if (makeinitializations) {
3315 c = list_first (&linkedclasses);
3318 c = list_next (&linkedclasses, c);
3322 intsRestore(); /* schani */
3325 static s4 classvalue;
3327 static void loader_compute_class_values (classinfo *c)
3331 c->vftbl->baseval = ++classvalue;
3334 while (subs != NULL) {
3335 loader_compute_class_values(subs);
3336 subs = subs->nextsub;
3338 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3343 for (i = 0; i < c->index; i++)
3345 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3346 utf_display(c->name);
3354 void loader_compute_subclasses ()
3358 intsDisable(); /* schani */
3360 c = list_first (&linkedclasses);
3362 if (!(c->flags & ACC_INTERFACE)) {
3366 c = list_next (&linkedclasses, c);
3369 c = list_first (&linkedclasses);
3371 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3372 c->nextsub = c->super->sub;
3375 c = list_next (&linkedclasses, c);
3378 loader_compute_class_values(class_java_lang_Object);
3380 intsRestore(); /* schani */
3385 /******************** function classloader_buffer ******************************
3387 sets buffer for reading classdata
3389 *******************************************************************************/
3391 void classload_buffer(u1 *buf, int len)
3394 classbuffer_size = len;
3395 classbuf_pos = buf - 1;
3399 /******************** Function: loader_close ***********************************
3403 *******************************************************************************/
3405 void loader_close ()
3409 while ( (c=list_first(&unloadedclasses)) ) {
3410 list_remove (&unloadedclasses,c);
3413 while ( (c=list_first(&unlinkedclasses)) ) {
3414 list_remove (&unlinkedclasses,c);
3417 while ( (c=list_first(&linkedclasses)) ) {
3418 list_remove (&linkedclasses,c);
3425 * These are local overrides for various environment variables in Emacs.
3426 * Please do not remove this and leave it at the end of the file, where
3427 * Emacs will automagically detect them.
3428 * ---------------------------------------------------------------------
3431 * indent-tabs-mode: t