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 696 2003-12-06 20:10:05Z edwin $
48 #include "toolbox/memory.h"
49 #include "toolbox/loging.h"
50 #include "threads/thread.h"
61 /* global variables ***********************************************************/
63 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
64 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
65 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
67 int count_class_infos = 0; /* variables for measurements */
68 int count_const_pool_len = 0;
69 int count_vftbl_len = 0;
70 int count_all_methods = 0;
71 int count_vmcode_len = 0;
72 int count_extable_len = 0;
73 int count_class_loads = 0;
74 int count_class_inits = 0;
76 bool loadverbose = false; /* switches for debug messages */
77 bool linkverbose = false;
78 bool initverbose = false;
80 bool makeinitializations = true;
82 bool getloadingtime = false; /* to measure the runtime */
83 long int loadingtime = 0;
85 static s4 interfaceindex; /* sequential numbering of interfaces */
87 list unloadedclasses; /* list of all referenced but not loaded classes */
88 list unlinkedclasses; /* list of all loaded but not linked classes */
89 list linkedclasses; /* list of all completely linked classes */
92 /* utf-symbols for pointer comparison of frequently used strings */
94 static utf *utf_innerclasses; /* InnerClasses */
95 static utf *utf_constantvalue; /* ConstantValue */
96 static utf *utf_code; /* Code */
97 static utf *utf_finalize; /* finalize */
98 static utf *utf_fidesc; /* ()V changed */
99 static utf *utf_clinit; /* <clinit> */
100 static utf *utf_initsystemclass; /* initializeSystemClass */
101 static utf *utf_systemclass; /* java/lang/System */
102 static utf *utf_vmclassloader; /*java/lang/VMClassLoader*/
103 static utf *utf_vmclass; /*java/lang/VMClassLoader*/
104 static utf *utf_initialize;
105 static utf *utf_initializedesc;
109 static unzFile uf = 0;
119 /* important system classes ***************************************************/
121 classinfo *class_java_lang_Object;
122 classinfo *class_java_lang_String;
124 classinfo *class_java_lang_Throwable;
125 classinfo *class_java_lang_Cloneable;
126 classinfo *class_java_io_Serializable;
128 /* Pseudo classes for the typechecker */
129 classinfo *pseudo_class_Arraystub = NULL;
130 classinfo *pseudo_class_Null = NULL;
131 vftbl *pseudo_class_Arraystub_vftbl = NULL;
134 /* These are made static so they cannot be used for throwing in native */
136 static classinfo *class_java_lang_ClassCastException;
137 static classinfo *class_java_lang_NullPointerException;
138 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
139 static classinfo *class_java_lang_NegativeArraySizeException;
140 static classinfo *class_java_lang_OutOfMemoryError;
141 static classinfo *class_java_lang_ArithmeticException;
142 static classinfo *class_java_lang_ArrayStoreException;
143 static classinfo *class_java_lang_ThreadDeath;
145 static methodinfo method_clone_array;
147 static int loader_inited = 0;
149 /******************************************************************************
151 structure for primitive classes: contains the class for wrapping the
152 primitive type, the primitive class, the name of the class for wrapping,
153 the one character type signature and the name of the primitive class
155 ******************************************************************************/
157 /* CAUTION: Don't change the order of the types. This table is indexed
158 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
160 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
161 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
162 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
163 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
164 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
165 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
166 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
167 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
168 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
169 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }};
171 /* instances of important system classes **************************************/
173 java_objectheader *proto_java_lang_ClassCastException;
174 java_objectheader *proto_java_lang_NullPointerException;
175 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
176 java_objectheader *proto_java_lang_NegativeArraySizeException;
177 java_objectheader *proto_java_lang_OutOfMemoryError;
178 java_objectheader *proto_java_lang_ArithmeticException;
179 java_objectheader *proto_java_lang_ArrayStoreException;
180 java_objectheader *proto_java_lang_ThreadDeath;
182 /************* functions for reading classdata *********************************
184 getting classdata in blocks of variable size
185 (8,16,32,64-bit integer or float)
187 *******************************************************************************/
189 static char *classpath = ""; /* searchpath for classfiles */
190 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
191 static u1 *classbuf_pos; /* current position in classfile buffer */
192 static int classbuffer_size; /* size of classfile-data */
194 /* transfer block of classfile data into a buffer */
196 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
199 /* skip block of classfile data */
201 #define skip_nbytes(len) classbuf_pos+=len;
205 return *++classbuf_pos;
209 u1 a=suck_u1(), b=suck_u1();
210 return ((u2)a<<8)+(u2)b;
214 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
215 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
217 #define suck_s8() (s8) suck_u8()
218 #define suck_s2() (s2) suck_u2()
219 #define suck_s4() (s4) suck_u4()
220 #define suck_s1() (s1) suck_u1()
223 /* get u8 from classfile data */
230 return (hi << 32) + lo;
240 /* get float from classfile data */
241 static float suck_float()
248 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
249 memcpy((u1*) (&f), buffer, 4);
251 suck_nbytes((u1*) (&f), 4);
254 PANICIF (sizeof(float) != 4, "Incompatible float-format");
260 /* get double from classfile data */
261 static double suck_double()
268 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
269 memcpy((u1*) (&d), buffer, 8);
271 suck_nbytes((u1*) (&d), 8);
274 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
280 /************************** function suck_init *********************************
282 called once at startup, sets the searchpath for the classfiles
284 *******************************************************************************/
286 void suck_init(char *cpath)
293 /************************** function suck_start ********************************
295 returns true if classbuffer is already loaded or a file for the
296 specified class has succussfully been read in. All directories of
297 the searchpath are used to find the classfile (<classname>.class).
298 Returns false if no classfile is found and writes an error message.
300 *******************************************************************************/
302 bool suck_start(utf *classname)
305 #define MAXFILENAME 1000 /* maximum length of a filename */
307 char filename[MAXFILENAME+10]; /* room for '.class' */
308 char *pathpos; /* position in searchpath */
309 char c, *utf_ptr; /* pointer to the next utf8-character */
311 int filenamelen, err;
315 if (classbuffer) /* classbuffer is already valid */
322 /* skip path separator */
324 while (*pathpos == ':')
327 /* extract directory from searchpath */
330 while ((*pathpos) && (*pathpos != ':')) {
331 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
332 filename[filenamelen++] = *(pathpos++);
336 if (filenamelen > 4) {
337 if ( ((filename[filenamelen - 1] == 'p') || (filename[filenamelen - 1] == 'P')) &
338 ((filename[filenamelen - 2] == 'i') || (filename[filenamelen - 2] == 'I')) &
339 ((filename[filenamelen - 3] == 'z') || (filename[filenamelen - 3] == 'Z')) ) {
346 filename[filenamelen++] = '\0';
347 if (uf == 0) uf = unzOpen(filename);
349 utf_ptr = classname->text;
351 while (utf_ptr < utf_end(classname)) {
352 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
354 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
356 filename[filenamelen++] = c;
358 strcpy(filename + filenamelen, ".class");
359 if (cacao_locate(uf,classname) == UNZ_OK) {
360 unz_file_info file_info;
361 log_text("Class found in zip file");
362 if (unzGetCurrentFileInfo(uf, &file_info, filename,
363 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
364 if (unzOpenCurrentFile(uf) == UNZ_OK) {
365 classbuffer_size = file_info.uncompressed_size;
366 classbuffer = MNEW(u1, classbuffer_size);
367 classbuf_pos = classbuffer - 1;
368 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
369 if (unzReadCurrentFile(uf, classbuffer, classbuffer_size) == classbuffer_size) {
370 unzCloseCurrentFile(uf);
373 MFREE(classbuffer, u1, classbuffer_size);
374 log_text("Error while unzipping");
376 } else log_text("Error while opening file in archive");
377 } else log_text("Error while retrieving fileinfo");
379 unzCloseCurrentFile(uf);
384 filename[filenamelen++] = '/';
386 /* add classname to filename */
388 utf_ptr = classname->text;
389 while (utf_ptr < utf_end(classname)) {
390 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
392 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
394 filename[filenamelen++] = c;
399 strcpy(filename + filenamelen, ".class");
401 classfile = fopen(filename, "r");
402 if (classfile) { /* file exists */
404 /* determine size of classfile */
406 err = stat(filename, &buffer);
408 if (!err) { /* read classfile data */
409 classbuffer_size = buffer.st_size;
410 classbuffer = MNEW(u1, classbuffer_size);
411 classbuf_pos = classbuffer - 1;
412 fread(classbuffer, 1, classbuffer_size, classfile);
420 dolog("Warning: Can not open class file '%s'", filename);
427 /************************** function suck_stop *********************************
429 frees memory for buffer with classfile data.
430 Caution: this function may only be called if buffer has been allocated
431 by suck_start with reading a file
433 *******************************************************************************/
437 /* determine amount of classdata not retrieved by suck-operations */
439 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
441 if (classdata_left > 0) {
443 dolog("There are %d access bytes at end of classfile",
449 MFREE(classbuffer, u1, classbuffer_size);
454 /******************************************************************************/
455 /******************* Some support functions ***********************************/
456 /******************************************************************************/
460 void fprintflags (FILE *fp, u2 f)
462 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
463 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
464 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
465 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
466 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
467 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
468 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
469 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
470 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
471 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
472 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
475 /********** internal function: printflags (only for debugging) ***************/
476 void printflags (u2 f)
478 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
479 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
480 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
481 if ( f & ACC_STATIC ) printf (" STATIC");
482 if ( f & ACC_FINAL ) printf (" FINAL");
483 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
484 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
485 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
486 if ( f & ACC_NATIVE ) printf (" NATIVE");
487 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
488 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
492 /************************* Function: skipattribute *****************************
494 skips a (1) 'attribute' structure in the class file
496 *******************************************************************************/
498 static void skipattribute ()
501 skip_nbytes(suck_u4());
504 /********************** Function: skipattributebody ****************************
506 skips an attribute after the 16 bit reference to attribute_name has already
509 *******************************************************************************/
511 static void skipattributebody ()
513 skip_nbytes(suck_u4());
516 /************************* Function: skipattributes ****************************
518 skips num attribute structures
520 *******************************************************************************/
522 static void skipattributes (u4 num)
525 for (i = 0; i < num; i++)
529 /******************** function: innerclass_getconstant ************************
531 like class_getconstant, but if cptags is ZERO null is returned
533 *******************************************************************************/
535 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
537 /* invalid position in constantpool */
538 if (pos >= c->cpcount)
539 panic ("Attempt to access constant outside range");
541 /* constantpool entry of type 0 */
545 /* check type of constantpool entry */
546 if (c->cptags[pos] != ctype) {
547 error ("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
548 (int) ctype, (int) c->cptags[pos] );
551 return c->cpinfos[pos];
554 /************************ function: attribute_load ****************************
556 read attributes from classfile
558 *******************************************************************************/
560 static void attribute_load (u4 num, classinfo *c)
564 for (i = 0; i < num; i++) {
565 /* retrieve attribute name */
566 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
568 if ( aname == utf_innerclasses) {
569 /* innerclasses attribute */
571 /* skip attribute length */
573 /* number of records */
574 c->innerclasscount = suck_u2();
575 /* allocate memory for innerclass structure */
576 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
578 for (j=0;j<c->innerclasscount;j++) {
580 /* The innerclass structure contains a class with an encoded name,
581 its defining scope, its simple name and a bitmask of the access flags.
582 If an inner class is not a member, its outer_class is NULL,
583 if a class is anonymous, its name is NULL. */
585 innerclassinfo *info = c->innerclass + j;
587 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
588 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
589 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
590 info->flags = suck_u2 (); /* access_flags bitmask */
593 /* unknown attribute */
594 skipattributebody ();
599 /******************* function: checkfielddescriptor ****************************
601 checks whether a field-descriptor is valid and aborts otherwise
602 all referenced classes are inserted into the list of unloaded classes
604 *******************************************************************************/
606 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
608 char *tstart; /* pointer to start of classname */
610 char *start = utf_ptr;
612 switch (*utf_ptr++) {
626 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
627 panic ("Ill formed descriptor");
631 panic ("Ill formed descriptor");
634 /* exceeding characters */
635 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
639 /******************* function checkmethoddescriptor ****************************
641 checks whether a method-descriptor is valid and aborts otherwise.
642 All referenced classes are inserted into the list of unloaded classes.
644 *******************************************************************************/
646 static void checkmethoddescriptor (utf *d)
648 char *utf_ptr = d->text; /* current position in utf text */
649 char *end_pos = utf_end(d); /* points behind utf string */
650 char *tstart; /* pointer to start of classname */
654 /* method descriptor must start with parenthesis */
655 /* XXX check length */
656 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
658 /* XXX check length */
659 /* check arguments */
660 while ((c = *utf_ptr++) != ')') {
677 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
678 panic ("Ill formed method descriptor");
682 panic ("Ill formed methodtype-descriptor");
686 /* check returntype */
688 /* returntype void */
689 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
692 /* treat as field-descriptor */
693 checkfielddescriptor (utf_ptr,end_pos);
696 /***************** Function: print_arraydescriptor ****************************
698 Debugging helper for displaying an arraydescriptor
700 *******************************************************************************/
703 print_arraydescriptor(FILE *file,arraydescriptor *desc)
706 fprintf(file,"<NULL>");
711 if (desc->componentvftbl) {
712 if (desc->componentvftbl->class)
713 utf_fprint(file,desc->componentvftbl->class->name);
715 fprintf(file,"<no classinfo>");
721 if (desc->elementvftbl) {
722 if (desc->elementvftbl->class)
723 utf_fprint(file,desc->elementvftbl->class->name);
725 fprintf(file,"<no classinfo>");
729 fprintf(file,",%d,%d,%d,%d}",desc->arraytype,desc->dimension,
730 desc->dataoffset,desc->componentsize);
733 /******************************************************************************/
734 /************************** Functions for fields ****************************/
735 /******************************************************************************/
738 /************************ Function: field_load *********************************
740 Load everything about a class field from the class file and fill a
741 'fieldinfo' structure. For static fields, space in the data segment is
744 *******************************************************************************/
746 static void field_load (fieldinfo *f, classinfo *c)
751 f -> flags = suck_u2 (); /* ACC flags */
752 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
753 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
754 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
755 f -> offset = 0; /* offset from start of object */
759 case TYPE_INT: f->value.i = 0; break;
760 case TYPE_FLOAT: f->value.f = 0.0; break;
761 case TYPE_DOUBLE: f->value.d = 0.0; break;
762 case TYPE_ADDRESS: f->value.a = NULL;
763 heap_addreference (&(f->value.a)); /* make global reference (GC) */
767 f->value.l = 0; break;
769 f->value.l.low = 0; f->value.l.high = 0; break;
773 /* read attributes */
775 for (i=0; i<attrnum; i++) {
779 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
781 if ( aname != utf_constantvalue ) {
782 /* unknown attribute */
783 skipattributebody ();
786 /* constant value attribute */
788 /* skip attribute length */
790 /* index of value in constantpool */
793 /* initialize field with value from constantpool */
796 constant_integer *ci =
797 class_getconstant(c, pindex, CONSTANT_Integer);
798 f->value.i = ci -> value;
804 class_getconstant(c, pindex, CONSTANT_Long);
806 f->value.l = cl -> value;
812 class_getconstant(c, pindex, CONSTANT_Float);
814 f->value.f = cf->value;
819 constant_double *cd =
820 class_getconstant(c, pindex, CONSTANT_Double);
822 f->value.d = cd->value;
827 utf *u = class_getconstant(c, pindex, CONSTANT_String);
828 /* create javastring from compressed utf8-string */
829 f->value.a = literalstring_new(u);
834 log_text ("Invalid Constant - Type");
843 /********************** function: field_free **********************************/
845 static void field_free (fieldinfo *f)
851 /**************** Function: field_display (debugging only) ********************/
853 void field_display (fieldinfo *f)
856 printflags (f -> flags);
858 utf_display (f -> name);
860 utf_display (f -> descriptor);
861 printf (" offset: %ld\n", (long int) (f -> offset) );
865 /******************************************************************************/
866 /************************* Functions for methods ******************************/
867 /******************************************************************************/
870 /*********************** Function: method_load *********************************
872 Loads a method from the class file and fills an existing 'methodinfo'
873 structure. For native methods, the function pointer field is set to the
874 real function pointer, for JavaVM methods a pointer to the compiler is used
877 *******************************************************************************/
879 static void method_load (methodinfo *m, classinfo *c)
889 m -> flags = suck_u2 ();
890 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
891 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
892 checkmethoddescriptor(m->descriptor);
895 m -> exceptiontable = NULL;
896 m -> entrypoint = NULL;
898 m -> stubroutine = NULL;
899 m -> methodUsed = NOTUSED;
900 m -> monoPoly = MONO;
902 m -> subRedefsUsed = 0;
906 if (! (m->flags & ACC_NATIVE) ) {
907 m -> stubroutine = createcompilerstub (m);
911 functionptr f = native_findfunction
912 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
914 m -> stubroutine = createnativestub (f, m);
920 for (i=0; i<attrnum; i++) {
923 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
925 if ( aname != utf_code) {
926 skipattributebody ();
929 if (m -> jcode) panic ("Two code-attributes for one method!");
932 m -> maxstack = suck_u2();
933 m -> maxlocals = suck_u2();
934 m -> jcodelength = suck_u4();
935 m -> jcode = MNEW (u1, m->jcodelength);
936 suck_nbytes (m->jcode, m->jcodelength);
937 m -> exceptiontablelength = suck_u2 ();
938 m -> exceptiontable =
939 MNEW (exceptiontable, m->exceptiontablelength);
942 count_vmcode_len += m->jcodelength + 18;
943 count_extable_len += 8 * m->exceptiontablelength;
946 for (e=0; e < m->exceptiontablelength; e++) {
948 m -> exceptiontable[e].startpc = suck_u2();
949 m -> exceptiontable[e].endpc = suck_u2();
950 m -> exceptiontable[e].handlerpc = suck_u2();
953 if (!idx) m -> exceptiontable[e].catchtype = NULL;
955 m -> exceptiontable[e].catchtype =
956 class_getconstant (c, idx, CONSTANT_Class);
960 skipattributes ( suck_u2() );
967 /********************* Function: method_free ***********************************
969 frees all memory that was allocated for this method
971 *******************************************************************************/
973 static void method_free (methodinfo *m)
975 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
976 if (m->exceptiontable)
977 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
978 if (m->mcode) CFREE (m->mcode, m->mcodelength);
979 if (m->stubroutine) {
980 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
981 else removecompilerstub (m->stubroutine);
986 /************** Function: method_display (debugging only) **************/
988 void method_display (methodinfo *m)
991 printflags (m -> flags);
993 utf_display (m -> name);
995 utf_display (m -> descriptor);
1000 /******************** Function: method_canoverwrite ****************************
1002 Check if m and old are identical with respect to type and name. This means
1003 that old can be overwritten with m.
1005 *******************************************************************************/
1007 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1009 if (m->name != old->name) return false;
1010 if (m->descriptor != old->descriptor) return false;
1011 if (m->flags & ACC_STATIC) return false;
1018 /******************************************************************************/
1019 /************************ Functions for class *********************************/
1020 /******************************************************************************/
1023 /******************** function:: class_getconstant ******************************
1025 retrieves the value at position 'pos' of the constantpool of a class
1026 if the type of the value is other than 'ctype' the system is stopped
1028 *******************************************************************************/
1030 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1032 /* invalid position in constantpool */
1033 if (pos >= c->cpcount)
1034 panic ("Attempt to access constant outside range");
1036 /* check type of constantpool entry */
1038 if (c->cptags[pos] != ctype) {
1039 class_showconstantpool(c);
1040 error ("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1041 (int) ctype, (int) c->cptags[pos] );
1044 return c->cpinfos[pos];
1048 /********************* Function: class_constanttype ****************************
1050 Determines the type of a class entry in the ConstantPool
1052 *******************************************************************************/
1054 u4 class_constanttype (classinfo *c, u4 pos)
1056 if (pos >= c->cpcount)
1057 panic ("Attempt to access constant outside range");
1058 return c->cptags[pos];
1062 /******************** function: class_loadcpool ********************************
1064 loads the constantpool of a class,
1065 the entries are transformed into a simpler format
1066 by resolving references
1067 (a detailed overview of the compact structures can be found in global.h)
1069 *******************************************************************************/
1071 static void class_loadcpool (classinfo *c)
1074 /* The following structures are used to save information which cannot be
1075 processed during the first pass. After the complete constantpool has
1076 been traversed the references can be resolved.
1077 (only in specific order) */
1079 /* CONSTANT_Class_info entries */
1080 typedef struct forward_class {
1081 struct forward_class *next;
1086 /* CONSTANT_String */
1087 typedef struct forward_string {
1088 struct forward_string *next;
1093 /* CONSTANT_NameAndType */
1094 typedef struct forward_nameandtype {
1095 struct forward_nameandtype *next;
1099 } forward_nameandtype;
1101 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1102 typedef struct forward_fieldmethint {
1103 struct forward_fieldmethint *next;
1107 u2 nameandtype_index;
1108 } forward_fieldmethint;
1112 long int dumpsize = dump_size ();
1114 forward_class *forward_classes = NULL;
1115 forward_string *forward_strings = NULL;
1116 forward_nameandtype *forward_nameandtypes = NULL;
1117 forward_fieldmethint *forward_fieldmethints = NULL;
1119 /* number of entries in the constant_pool table */
1120 u4 cpcount = c -> cpcount = suck_u2();
1121 /* allocate memory */
1122 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1123 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1126 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1129 /* initialize constantpool */
1130 for (idx=0; idx<cpcount; idx++) {
1131 cptags[idx] = CONSTANT_UNUSED;
1132 cpinfos[idx] = NULL;
1136 /******* first pass *******/
1137 /* entries which cannot be resolved now are written into
1138 temporary structures and traversed again later */
1141 while (idx < cpcount) {
1142 /* get constant type */
1146 case CONSTANT_Class: {
1147 forward_class *nfc = DNEW(forward_class);
1149 nfc -> next = forward_classes;
1150 forward_classes = nfc;
1152 nfc -> thisindex = idx;
1153 /* reference to CONSTANT_NameAndType */
1154 nfc -> name_index = suck_u2 ();
1160 case CONSTANT_Fieldref:
1161 case CONSTANT_Methodref:
1162 case CONSTANT_InterfaceMethodref: {
1163 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1165 nff -> next = forward_fieldmethints;
1166 forward_fieldmethints = nff;
1168 nff -> thisindex = idx;
1171 /* class or interface type that contains the declaration of the field or method */
1172 nff -> class_index = suck_u2 ();
1173 /* name and descriptor of the field or method */
1174 nff -> nameandtype_index = suck_u2 ();
1180 case CONSTANT_String: {
1181 forward_string *nfs = DNEW (forward_string);
1183 nfs -> next = forward_strings;
1184 forward_strings = nfs;
1186 nfs -> thisindex = idx;
1187 /* reference to CONSTANT_Utf8_info with string characters */
1188 nfs -> string_index = suck_u2 ();
1194 case CONSTANT_NameAndType: {
1195 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1197 nfn -> next = forward_nameandtypes;
1198 forward_nameandtypes = nfn;
1200 nfn -> thisindex = idx;
1201 /* reference to CONSTANT_Utf8_info containing simple name */
1202 nfn -> name_index = suck_u2 ();
1203 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1204 nfn -> sig_index = suck_u2 ();
1210 case CONSTANT_Integer: {
1211 constant_integer *ci = NEW (constant_integer);
1214 count_const_pool_len += sizeof(constant_integer);
1217 ci -> value = suck_s4 ();
1218 cptags [idx] = CONSTANT_Integer;
1225 case CONSTANT_Float: {
1226 constant_float *cf = NEW (constant_float);
1229 count_const_pool_len += sizeof(constant_float);
1232 cf -> value = suck_float ();
1233 cptags [idx] = CONSTANT_Float;
1239 case CONSTANT_Long: {
1240 constant_long *cl = NEW(constant_long);
1243 count_const_pool_len += sizeof(constant_long);
1246 cl -> value = suck_s8 ();
1247 cptags [idx] = CONSTANT_Long;
1253 case CONSTANT_Double: {
1254 constant_double *cd = NEW(constant_double);
1257 count_const_pool_len += sizeof(constant_double);
1260 cd -> value = suck_double ();
1261 cptags [idx] = CONSTANT_Double;
1267 case CONSTANT_Utf8: {
1269 /* number of bytes in the bytes array (not string-length) */
1270 u4 length = suck_u2();
1271 cptags [idx] = CONSTANT_Utf8;
1272 /* insert utf-string into the utf-symboltable */
1273 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1274 /* skip bytes of the string */
1275 skip_nbytes(length);
1281 error ("Unkown constant type: %d",(int) t);
1289 /* resolve entries in temporary structures */
1291 while (forward_classes) {
1293 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1295 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1296 /* retrieve class from class-table */
1297 cpinfos [forward_classes -> thisindex] = class_new (name);
1299 forward_classes = forward_classes -> next;
1303 while (forward_strings) {
1305 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1307 log_text("forward_string:");
1308 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1310 log_text("\n------------------"); */
1311 /* resolve utf-string */
1312 cptags [forward_strings -> thisindex] = CONSTANT_String;
1313 cpinfos [forward_strings -> thisindex] = text;
1315 forward_strings = forward_strings -> next;
1318 while (forward_nameandtypes) {
1319 constant_nameandtype *cn = NEW (constant_nameandtype);
1322 count_const_pool_len += sizeof(constant_nameandtype);
1325 /* resolve simple name and descriptor */
1326 cn -> name = class_getconstant
1327 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1328 cn -> descriptor = class_getconstant
1329 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1331 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1332 cpinfos [forward_nameandtypes -> thisindex] = cn;
1334 forward_nameandtypes = forward_nameandtypes -> next;
1338 while (forward_fieldmethints) {
1339 constant_nameandtype *nat;
1340 constant_FMIref *fmi = NEW (constant_FMIref);
1343 count_const_pool_len += sizeof(constant_FMIref);
1345 /* resolve simple name and descriptor */
1346 nat = class_getconstant
1347 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1350 log_text("trying to resolve:");
1351 log_text(nat->name->text);
1352 switch(forward_fieldmethints ->tag) {
1353 case CONSTANT_Fieldref:
1354 log_text("CONSTANT_Fieldref");
1356 case CONSTANT_InterfaceMethodref:
1357 log_text("CONSTANT_InterfaceMethodref");
1359 case CONSTANT_Methodref:
1360 log_text("CONSTANT_Methodref");
1364 fmi -> class = class_getconstant
1365 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1366 fmi -> name = nat -> name;
1367 fmi -> descriptor = nat -> descriptor;
1369 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1370 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1372 switch (forward_fieldmethints -> tag) {
1373 case CONSTANT_Fieldref: /* check validity of descriptor */
1374 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1376 case CONSTANT_InterfaceMethodref:
1377 case CONSTANT_Methodref: /* check validity of descriptor */
1378 checkmethoddescriptor (fmi->descriptor);
1382 forward_fieldmethints = forward_fieldmethints -> next;
1386 /* class_showconstantpool(c); */
1388 dump_release (dumpsize);
1392 /********************** Function: class_load ***********************************
1394 Loads everything interesting about a class from the class file. The
1395 'classinfo' structure must have been allocated previously.
1397 The super class and the interfaces implemented by this class need not be
1398 loaded. The link is set later by the function 'class_link'.
1400 The loaded class is removed from the list 'unloadedclasses' and added to
1401 the list 'unlinkedclasses'.
1403 *******************************************************************************/
1405 static int class_load(classinfo *c)
1411 count_class_loads++;
1414 /* output for debugging purposes */
1416 char logtext[MAXLOGTEXT];
1417 sprintf(logtext, "Loading class: ");
1418 utf_sprint(logtext+strlen(logtext), c->name);
1422 /* load classdata, throw exception on error */
1424 if (!suck_start(c->name)) {
1425 throw_classnotfoundexception2(c->name);
1429 /* check signature */
1430 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1434 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1435 error ("File version %d.%d is not supported",
1436 (int) ma, (int) mi);
1439 class_loadcpool (c);
1441 c->erroneous_state=0;
1442 c->initializing_thread=0;
1444 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1445 c -> impldBy = NULL;
1448 c -> flags = suck_u2 ();
1449 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1454 /* retrieve superclass */
1455 if ( (i = suck_u2 () ) ) {
1456 c -> super = class_getconstant (c, i, CONSTANT_Class);
1462 /* retrieve interfaces */
1463 c -> interfacescount = suck_u2 ();
1464 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1465 for (i=0; i < c -> interfacescount; i++) {
1466 c -> interfaces [i] =
1467 class_getconstant (c, suck_u2(), CONSTANT_Class);
1471 c -> fieldscount = suck_u2 ();
1472 /* utf_display(c->name);
1473 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1475 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1476 for (i=0; i < c -> fieldscount; i++) {
1477 field_load (&(c->fields[i]), c);
1481 c -> methodscount = suck_u2 ();
1482 c -> methods = MNEW (methodinfo, c -> methodscount);
1483 for (i=0; i < c -> methodscount; i++) {
1484 method_load (&(c -> methods [i]), c);
1488 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1489 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1490 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1493 /* load variable-length attribute structures */
1494 attribute_load (suck_u2(), c);
1499 /* remove class from list of unloaded classes and
1500 add to list of unlinked classes */
1501 list_remove (&unloadedclasses, c);
1502 list_addlast (&unlinkedclasses, c);
1509 /************** internal Function: class_highestinterface ***********************
1511 Used by the function class_link to determine the amount of memory needed
1512 for the interface table.
1514 *******************************************************************************/
1516 static s4 class_highestinterface (classinfo *c)
1521 if ( ! (c->flags & ACC_INTERFACE) ) {
1522 char logtext[MAXLOGTEXT];
1523 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1524 utf_sprint (logtext+strlen(logtext), c->name);
1529 for (i=0; i<c->interfacescount; i++) {
1530 s4 h2 = class_highestinterface (c->interfaces[i]);
1537 /* class_addinterface **********************************************************
1539 Is needed by class_link for adding a VTBL to a class. All interfaces
1540 implemented by ic are added as well.
1542 *******************************************************************************/
1544 static void class_addinterface (classinfo *c, classinfo *ic)
1548 vftbl *vftbl = c->vftbl;
1550 if (i >= vftbl->interfacetablelength)
1551 panic ("Inernal error: interfacetable overflow");
1552 if (vftbl->interfacetable[-i])
1555 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1556 vftbl->interfacevftbllength[i] = 1;
1557 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1558 vftbl->interfacetable[-i][0] = NULL;
1561 vftbl->interfacevftbllength[i] = ic->methodscount;
1562 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1565 count_vftbl_len += sizeof(methodptr) *
1566 (ic->methodscount + (ic->methodscount == 0));
1569 for (j=0; j<ic->methodscount; j++) {
1572 for (m = 0; m < sc->methodscount; m++) {
1573 methodinfo *mi = &(sc->methods[m]);
1574 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1575 vftbl->interfacetable[-i][j] =
1576 vftbl->table[mi->vftblindex];
1586 for (j = 0; j < ic->interfacescount; j++)
1587 class_addinterface(c, ic->interfaces[j]);
1591 /******************* Function: class_new_array *********************************
1593 This function is called by class_new to setup an array class.
1595 *******************************************************************************/
1598 class_new_array(classinfo *c)
1600 classinfo *comp = NULL;
1604 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1606 /* Array classes are not loaded from classfiles. */
1607 list_remove (&unloadedclasses, c);
1609 /* Check array class name */
1610 namelen = c->name->blength;
1611 if (namelen < 2 || c->name->text[0] != '[')
1612 panic("Invalid array class name.");
1614 /* Check the component type */
1615 switch (c->name->text[1]) {
1617 /* c is an array of arrays. We have to create the component class. */
1618 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1622 /* c is an array of objects. */
1623 if (namelen < 4 || c->name->text[namelen-1] != ';')
1624 panic("Invalid array class name.");
1625 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1629 /* Setup the array class */
1630 c->super = class_java_lang_Object;
1632 c->interfacescount = 2;
1633 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1634 c->interfaces[0] = class_java_lang_Cloneable;
1635 c->interfaces[1] = class_java_io_Serializable;
1637 c->methodscount = 1;
1638 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1641 memset(clone,0,sizeof(methodinfo));
1642 clone->flags = ACC_PUBLIC; /* XXX protected? */
1643 clone->name = utf_new_char("clone");
1644 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1646 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1647 clone->monoPoly = MONO; /* XXX should be poly? */
1649 /* XXX: field: length? */
1651 /* The array class has to be linked */
1652 list_addlast(&unlinkedclasses,c);
1655 * Array classes which are created after the other classes have been
1656 * loaded and linked are linked explicitely.
1661 loader_load(c->name);
1664 /****************** Function: class_link_array *********************************
1666 This function is called by class_link to create the
1667 arraydescriptor for an array class.
1669 This function returns NULL if the array cannot be linked because
1670 the component type has not been linked yet.
1672 *******************************************************************************/
1676 class_link_array(classinfo *c)
1678 classinfo *comp = NULL;
1679 int namelen = c->name->blength;
1680 arraydescriptor *desc;
1683 /* Check the component type */
1684 switch (c->name->text[1]) {
1686 /* c is an array of arrays. */
1687 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1688 if (!comp) panic("Could not find component array class.");
1692 /* c is an array of objects. */
1693 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1694 if (!comp) panic("Could not find component class.");
1698 /* If the component type has not been linked return NULL */
1699 if (comp && !comp->linked)
1702 /* Allocate the arraydescriptor */
1703 desc = NEW(arraydescriptor);
1706 /* c is an array of references */
1707 desc->arraytype = ARRAYTYPE_OBJECT;
1708 desc->componentsize = sizeof(void*);
1709 desc->dataoffset = OFFSET(java_objectarray,data);
1711 compvftbl = comp->vftbl;
1713 panic("Component class has no vftbl.");
1714 desc->componentvftbl = compvftbl;
1716 if (compvftbl->arraydesc) {
1717 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1718 desc->dimension = compvftbl->arraydesc->dimension + 1;
1719 desc->elementtype = compvftbl->arraydesc->elementtype;
1722 desc->elementvftbl = compvftbl;
1723 desc->dimension = 1;
1724 desc->elementtype = ARRAYTYPE_OBJECT;
1728 /* c is an array of a primitive type */
1729 switch (c->name->text[1]) {
1730 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1731 desc->dataoffset = OFFSET(java_booleanarray,data);
1732 desc->componentsize = sizeof(u1); break;
1733 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1734 desc->dataoffset = OFFSET(java_bytearray,data);
1735 desc->componentsize = sizeof(u1); break;
1736 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1737 desc->dataoffset = OFFSET(java_chararray,data);
1738 desc->componentsize = sizeof(u2); break;
1739 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1740 desc->dataoffset = OFFSET(java_doublearray,data);
1741 desc->componentsize = sizeof(double); break;
1742 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1743 desc->dataoffset = OFFSET(java_floatarray,data);
1744 desc->componentsize = sizeof(float); break;
1745 case 'I': desc->arraytype = ARRAYTYPE_INT;
1746 desc->dataoffset = OFFSET(java_intarray,data);
1747 desc->componentsize = sizeof(s4); break;
1748 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1749 desc->dataoffset = OFFSET(java_longarray,data);
1750 desc->componentsize = sizeof(s8); break;
1751 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1752 desc->dataoffset = OFFSET(java_shortarray,data);
1753 desc->componentsize = sizeof(s2); break;
1755 panic("Invalid array class name");
1758 desc->componentvftbl = NULL;
1759 desc->elementvftbl = NULL;
1760 desc->dimension = 1;
1761 desc->elementtype = desc->arraytype;
1767 /********************** Function: class_link ***********************************
1769 Tries to link a class. The super class and every implemented interface must
1770 already have been linked. The function calculates the length in bytes that
1771 an instance of this class requires as well as the VTBL for methods and
1774 If the class can be linked, it is removed from the list 'unlinkedclasses'
1775 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1778 Attention: If cyclical class definitions are encountered, the program gets
1779 into an infinite loop (we'll have to work that out)
1781 *******************************************************************************/
1783 void class_link(classinfo *c)
1785 s4 supervftbllength; /* vftbllegnth of super class */
1786 s4 vftbllength; /* vftbllength of current class */
1787 s4 interfacetablelength; /* interface table length */
1788 classinfo *super = c->super; /* super class */
1789 classinfo *ic, *c2; /* intermediate class variables */
1790 vftbl *v; /* vftbl of current class */
1791 s4 i; /* interface/method/field counter */
1792 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1795 /* check if all superclasses are already linked, if not put c at end of
1796 unlinked list and return. Additionally initialize class fields. */
1798 /* check interfaces */
1800 for (i = 0; i < c->interfacescount; i++) {
1801 ic = c->interfaces[i];
1803 list_remove(&unlinkedclasses, c);
1804 list_addlast(&unlinkedclasses, c);
1809 /* check super class */
1811 if (super == NULL) { /* class java.long.Object */
1813 c->classUsed = USED; /* Object class is always used CO-RT*/
1814 c -> impldBy = NULL;
1815 c->instancesize = sizeof(java_objectheader);
1817 vftbllength = supervftbllength = 0;
1819 c->finalizer = NULL;
1822 if (!super->linked) {
1823 list_remove(&unlinkedclasses, c);
1824 list_addlast(&unlinkedclasses, c);
1828 /* handle array classes */
1829 if (c->name->text[0] == '[')
1830 if ((arraydesc = class_link_array(c)) == NULL) {
1831 list_remove(&unlinkedclasses, c);
1832 list_addlast(&unlinkedclasses, c);
1836 if (c->flags & ACC_INTERFACE)
1837 c->index = interfaceindex++;
1839 c->index = super->index + 1;
1841 c->instancesize = super->instancesize;
1843 vftbllength = supervftbllength = super->vftbl->vftbllength;
1845 c->finalizer = super->finalizer;
1850 char logtext[MAXLOGTEXT];
1851 sprintf (logtext, "Linking Class: ");
1852 utf_sprint (logtext+strlen(logtext), c->name );
1856 /* compute vftbl length */
1858 for (i = 0; i < c->methodscount; i++) {
1859 methodinfo *m = &(c->methods[i]);
1861 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1862 classinfo *sc = super;
1865 for (j = 0; j < sc->methodscount; j++) {
1866 if (method_canoverwrite(m, &(sc->methods[j]))) {
1867 m->vftblindex = sc->methods[j].vftblindex;
1868 goto foundvftblindex;
1873 m->vftblindex = (vftbllength++);
1879 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1882 /* compute interfacetable length */
1884 interfacetablelength = 0;
1887 for (i = 0; i < c2->interfacescount; i++) {
1888 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1889 if (h > interfacetablelength)
1890 interfacetablelength = h;
1895 /* allocate virtual function table */
1897 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1898 (vftbllength - 1) + sizeof(methodptr*) *
1899 (interfacetablelength - (interfacetablelength > 0)));
1900 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1901 (interfacetablelength > 1));
1902 c->header.vftbl = c->vftbl = v;
1904 v->vftbllength = vftbllength;
1905 v->interfacetablelength = interfacetablelength;
1906 v->arraydesc = arraydesc;
1908 /* store interface index in vftbl */
1909 if (c->flags & ACC_INTERFACE)
1910 v->baseval = -(c->index);
1912 /* copy virtual function table of super class */
1914 for (i = 0; i < supervftbllength; i++)
1915 v->table[i] = super->vftbl->table[i];
1917 /* add method stubs into virtual function table */
1919 for (i = 0; i < c->methodscount; i++) {
1920 methodinfo *m = &(c->methods[i]);
1921 if (!(m->flags & ACC_STATIC)) {
1922 v->table[m->vftblindex] = m->stubroutine;
1926 /* compute instance size and offset of each field */
1928 for (i = 0; i < c->fieldscount; i++) {
1930 fieldinfo *f = &(c->fields[i]);
1932 if (!(f->flags & ACC_STATIC) ) {
1933 dsize = desc_typesize (f->descriptor);
1934 c->instancesize = ALIGN (c->instancesize, dsize);
1935 f->offset = c->instancesize;
1936 c->instancesize += dsize;
1940 /* initialize interfacetable and interfacevftbllength */
1942 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1945 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1948 for (i = 0; i < interfacetablelength; i++) {
1949 v->interfacevftbllength[i] = 0;
1950 v->interfacetable[-i] = NULL;
1953 /* add interfaces */
1955 for (c2 = c; c2 != NULL; c2 = c2->super)
1956 for (i = 0; i < c2->interfacescount; i++) {
1957 class_addinterface (c, c2->interfaces[i]);
1960 /* add finalizer method (not for java.lang.Object) */
1962 if (super != NULL) {
1964 static utf *finame = NULL;
1965 static utf *fidesc = NULL;
1968 finame = utf_finalize;
1970 fidesc = utf_fidesc;
1972 fi = class_findmethod (c, finame, fidesc);
1974 if (!(fi->flags & ACC_STATIC)) {
1984 list_remove (&unlinkedclasses, c);
1985 list_addlast (&linkedclasses, c);
1990 /******************* Function: class_freepool **********************************
1992 Frees all resources used by this classes Constant Pool.
1994 *******************************************************************************/
1996 static void class_freecpool (classinfo *c)
2002 for (idx=0; idx < c->cpcount; idx++) {
2003 tag = c->cptags[idx];
2004 info = c->cpinfos[idx];
2008 case CONSTANT_Fieldref:
2009 case CONSTANT_Methodref:
2010 case CONSTANT_InterfaceMethodref:
2011 FREE (info, constant_FMIref);
2013 case CONSTANT_Integer:
2014 FREE (info, constant_integer);
2016 case CONSTANT_Float:
2017 FREE (info, constant_float);
2020 FREE (info, constant_long);
2022 case CONSTANT_Double:
2023 FREE (info, constant_double);
2025 case CONSTANT_NameAndType:
2026 FREE (info, constant_nameandtype);
2032 MFREE (c -> cptags, u1, c -> cpcount);
2033 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2037 /*********************** Function: class_free **********************************
2039 Frees all resources used by the class.
2041 *******************************************************************************/
2043 static void class_free (classinfo *c)
2048 class_freecpool (c);
2050 MFREE (c->interfaces, classinfo*, c->interfacescount);
2052 for (i = 0; i < c->fieldscount; i++)
2053 field_free(&(c->fields[i]));
2055 for (i = 0; i < c->methodscount; i++)
2056 method_free(&(c->methods[i]));
2057 MFREE (c->methods, methodinfo, c->methodscount);
2059 if ((v = c->vftbl) != NULL) {
2061 mem_free(v->arraydesc,sizeof(arraydescriptor));
2063 for (i = 0; i < v->interfacetablelength; i++) {
2064 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2066 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2068 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2069 sizeof(methodptr*) * (v->interfacetablelength -
2070 (v->interfacetablelength > 0));
2071 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2072 (v->interfacetablelength > 1));
2076 if (c->innerclasscount)
2077 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2079 /* if (c->classvftbl)
2080 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2082 FREE (c, classinfo);
2085 /************************* Function: class_findfield ***************************
2087 Searches a 'classinfo' structure for a field having the given name and
2090 *******************************************************************************/
2093 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2098 for (i = 0; i < c->fieldscount; i++) {
2099 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2100 return &(c->fields[i]);
2103 panic ("Can not find field given in CONSTANT_Fieldref");
2108 /************************* Function: class_findmethod **************************
2110 Searches a 'classinfo' structure for a method having the given name and
2111 type and returns the index in the class info structure.
2112 If type is NULL, it is ignored.
2114 *******************************************************************************/
2116 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2119 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2121 int buffer_len, pos;
2123 #ifdef JOWENN_DEBUG1
2126 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2128 buffer = MNEW(char, buffer_len);
2130 strcpy(buffer, "class_findmethod: method:");
2131 utf_sprint(buffer+strlen(buffer), name);
2132 strcpy(buffer+strlen(buffer), ", desc: ");
2133 utf_sprint(buffer+strlen(buffer), desc);
2134 strcpy(buffer+strlen(buffer), ", classname: ");
2135 utf_sprint(buffer+strlen(buffer), c->name);
2139 MFREE(buffer, char, buffer_len);
2141 for (i = 0; i < c->methodscount; i++) {
2142 #ifdef JOWENN_DEBUG2
2144 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2146 buffer = MNEW(char, buffer_len);
2148 strcpy(buffer, "class_findmethod: comparing to method:");
2149 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2150 strcpy(buffer+strlen(buffer), ", desc: ");
2151 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2155 MFREE(buffer, char, buffer_len);
2159 if ((c->methods[i].name == name) && ((desc == NULL) ||
2160 (c->methods[i].descriptor == desc)))
2163 #ifdef JOWENN_DEBUG2
2164 class_showconstantpool(c);
2165 log_text("class_findmethod: returning NULL");
2172 /************************* Function: class_findmethod **************************
2174 Searches a 'classinfo' structure for a method having the given name and
2176 If type is NULL, it is ignored.
2178 *******************************************************************************/
2180 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2184 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2186 int buffer_len, pos;
2188 #ifdef JOWENN_DEBUG1
2191 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2193 buffer = MNEW(char, buffer_len);
2195 strcpy(buffer, "class_findmethod: method:");
2196 utf_sprint(buffer+strlen(buffer), name);
2197 strcpy(buffer+strlen(buffer), ", desc: ");
2198 utf_sprint(buffer+strlen(buffer), desc);
2199 strcpy(buffer+strlen(buffer), ", classname: ");
2200 utf_sprint(buffer+strlen(buffer), c->name);
2204 MFREE(buffer, char, buffer_len);
2206 for (i = 0; i < c->methodscount; i++) {
2207 #ifdef JOWENN_DEBUG2
2209 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2211 buffer = MNEW(char, buffer_len);
2213 strcpy(buffer, "class_findmethod: comparing to method:");
2214 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2215 strcpy(buffer+strlen(buffer), ", desc: ");
2216 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2220 MFREE(buffer, char, buffer_len);
2224 if ((c->methods[i].name == name) && ((desc == NULL) ||
2225 (c->methods[i].descriptor == desc)))
2226 return &(c->methods[i]);
2228 #ifdef JOWENN_DEBUG2
2229 class_showconstantpool(c);
2230 log_text("class_findmethod: returning NULL");
2234 s4 idx=class_findmethodIndex(c,name,desc);
2235 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2236 if (idx==-1) return NULL;
2237 return &(c->methods[idx]);
2245 /************************* Function: class_findmethod_approx ******************
2247 like class_findmethod but ignores the return value when comparing the
2250 *******************************************************************************/
2252 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2256 for (i = 0; i < c->methodscount; i++)
2257 if (c->methods[i].name == name) {
2258 utf *meth_descr = c->methods[i].descriptor;
2262 return &(c->methods[i]);
2264 if (desc->blength <= meth_descr->blength) {
2265 /* current position in utf text */
2266 char *desc_utf_ptr = desc->text;
2267 char *meth_utf_ptr = meth_descr->text;
2268 /* points behind utf strings */
2269 char *desc_end = utf_end(desc);
2270 char *meth_end = utf_end(meth_descr);
2273 /* compare argument types */
2274 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2276 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2277 break; /* no match */
2280 return &(c->methods[i]); /* all parameter types equal */
2288 /***************** Function: class_resolvemethod_approx ***********************
2290 Searches a class and every super class for a method (without paying
2291 attention to the return value)
2293 *******************************************************************************/
2295 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2298 /* search for method (ignore returntype) */
2299 methodinfo *m = class_findmethod_approx (c, name, desc);
2302 /* search superclass */
2309 /************************* Function: class_resolvemethod ***********************
2311 Searches a class and every super class for a method.
2313 *******************************************************************************/
2315 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2318 methodinfo *m = class_findmethod(c, name, desc);
2320 /* search superclass */
2328 /************************* Function: class_issubclass **************************
2330 Checks if sub is a descendant of super.
2332 *******************************************************************************/
2334 bool class_issubclass(classinfo *sub, classinfo *super)
2337 if (!sub) return false;
2338 if (sub==super) return true;
2345 /****************** Initialization function for classes ******************
2347 In Java, every class can have a static initialization function. This
2348 function has to be called BEFORE calling other methods or accessing static
2351 *******************************************************************************/
2354 extern int blockInts;
2357 void class_init(classinfo *c)
2360 java_objectheader *exceptionptr;
2365 if (!makeinitializations)
2369 c -> initialized = true;
2374 count_class_inits++;
2378 class_init (c->super);
2379 for (i=0; i < c->interfacescount; i++)
2380 class_init(c->interfaces[i]); /* real */
2382 m = class_findmethod (c, utf_clinit, utf_fidesc);
2385 char logtext[MAXLOGTEXT];
2386 sprintf (logtext, "Class ");
2387 utf_sprint (logtext+strlen(logtext), c->name);
2388 sprintf (logtext+strlen(logtext), " has no initializer");
2391 /* goto callinitialize;*/
2395 if (! (m->flags & ACC_STATIC))
2396 panic ("Class initializer is not static!");
2399 char logtext[MAXLOGTEXT];
2400 sprintf (logtext, "Starting initializer for class: ");
2401 utf_sprint (logtext+strlen(logtext), c->name);
2410 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2413 assert(blockInts == 0);
2418 printf ("#### Initializer of ");
2419 utf_display (c->name);
2420 printf (" has thrown: ");
2421 utf_display (exceptionptr->vftbl->class->name);
2427 char logtext[MAXLOGTEXT];
2428 sprintf (logtext, "Finished initializer for class: ");
2429 utf_sprint (logtext+strlen(logtext), c->name);
2432 if (c->name == utf_systemclass) {
2433 /* class java.lang.System requires explicit initialization */
2436 printf ("#### Initializing class System");
2438 /* find initializing method */
2439 m = class_findmethod (c,
2440 utf_initsystemclass,
2444 /* no method found */
2445 /* printf("initializeSystemClass failed"); */
2453 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2456 assert(blockInts == 0);
2461 printf ("#### initializeSystemClass has thrown: ");
2462 utf_display (exceptionptr->vftbl->class->name);
2473 /********* Function: find_class_method_constant *********/
2474 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2479 for (i=0; i<c->cpcount; i++) {
2481 e = c -> cpinfos [i];
2484 switch (c -> cptags [i]) {
2485 case CONSTANT_Methodref:
2487 constant_FMIref *fmi = e;
2488 if ( (fmi->class->name == c1)
2489 && (fmi->name == m1)
2490 && (fmi->descriptor == d1)) {
2497 case CONSTANT_InterfaceMethodref:
2499 constant_FMIref *fmi = e;
2500 if ( (fmi->class->name == c1)
2501 && (fmi->name == m1)
2502 && (fmi->descriptor == d1)) {
2516 void class_showconstanti(classinfo *c, int ii)
2522 printf ("#%d: ", (int) i);
2524 switch (c->cptags [i]) {
2525 case CONSTANT_Class:
2526 printf("Classreference -> ");
2527 utf_display(((classinfo*)e)->name);
2530 case CONSTANT_Fieldref:
2531 printf("Fieldref -> "); goto displayFMIi;
2532 case CONSTANT_Methodref:
2533 printf("Methodref -> "); goto displayFMIi;
2534 case CONSTANT_InterfaceMethodref:
2535 printf("InterfaceMethod -> "); goto displayFMIi;
2538 constant_FMIref *fmi = e;
2539 utf_display(fmi->class->name);
2541 utf_display(fmi->name);
2543 utf_display(fmi->descriptor);
2547 case CONSTANT_String:
2548 printf("String -> ");
2551 case CONSTANT_Integer:
2552 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2554 case CONSTANT_Float:
2555 printf("Float -> %f", ((constant_float*)e)->value);
2557 case CONSTANT_Double:
2558 printf("Double -> %f", ((constant_double*)e)->value);
2562 u8 v = ((constant_long*)e)->value;
2564 printf("Long -> %ld", (long int) v);
2566 printf("Long -> HI: %ld, LO: %ld\n",
2567 (long int) v.high, (long int) v.low);
2571 case CONSTANT_NameAndType:
2573 constant_nameandtype *cnt = e;
2574 printf("NameAndType: ");
2575 utf_display(cnt->name);
2577 utf_display(cnt->descriptor);
2585 panic("Invalid type of ConstantPool-Entry");
2592 void class_showconstantpool (classinfo *c)
2597 printf ("---- dump of constant pool ----\n");
2599 for (i=0; i<c->cpcount; i++) {
2600 printf ("#%d: ", (int) i);
2602 e = c -> cpinfos [i];
2605 switch (c -> cptags [i]) {
2606 case CONSTANT_Class:
2607 printf ("Classreference -> ");
2608 utf_display ( ((classinfo*)e) -> name );
2611 case CONSTANT_Fieldref:
2612 printf ("Fieldref -> "); goto displayFMI;
2613 case CONSTANT_Methodref:
2614 printf ("Methodref -> "); goto displayFMI;
2615 case CONSTANT_InterfaceMethodref:
2616 printf ("InterfaceMethod -> "); goto displayFMI;
2619 constant_FMIref *fmi = e;
2620 utf_display ( fmi->class->name );
2622 utf_display ( fmi->name);
2624 utf_display ( fmi->descriptor );
2628 case CONSTANT_String:
2629 printf ("String -> ");
2632 case CONSTANT_Integer:
2633 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2635 case CONSTANT_Float:
2636 printf ("Float -> %f", ((constant_float*)e) -> value);
2638 case CONSTANT_Double:
2639 printf ("Double -> %f", ((constant_double*)e) -> value);
2643 u8 v = ((constant_long*)e) -> value;
2645 printf ("Long -> %ld", (long int) v);
2647 printf ("Long -> HI: %ld, LO: %ld\n",
2648 (long int) v.high, (long int) v.low);
2652 case CONSTANT_NameAndType:
2654 constant_nameandtype *cnt = e;
2655 printf ("NameAndType: ");
2656 utf_display (cnt->name);
2658 utf_display (cnt->descriptor);
2662 printf ("Utf8 -> ");
2666 panic ("Invalid type of ConstantPool-Entry");
2676 /********** Function: class_showmethods (debugging only) *************/
2678 void class_showmethods (classinfo *c)
2682 printf ("--------- Fields and Methods ----------------\n");
2683 printf ("Flags: "); printflags (c->flags); printf ("\n");
2685 printf ("This: "); utf_display (c->name); printf ("\n");
2687 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2689 printf ("Index: %d\n", c->index);
2691 printf ("interfaces:\n");
2692 for (i=0; i < c-> interfacescount; i++) {
2694 utf_display (c -> interfaces[i] -> name);
2695 printf (" (%d)\n", c->interfaces[i] -> index);
2698 printf ("fields:\n");
2699 for (i=0; i < c -> fieldscount; i++) {
2700 field_display (&(c -> fields[i]));
2703 printf ("methods:\n");
2704 for (i=0; i < c -> methodscount; i++) {
2705 methodinfo *m = &(c->methods[i]);
2706 if ( !(m->flags & ACC_STATIC))
2707 printf ("vftblindex: %d ", m->vftblindex);
2709 method_display ( m );
2713 printf ("Virtual function table:\n");
2714 for (i=0; i<c->vftbl->vftbllength; i++) {
2715 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2722 /******************************************************************************/
2723 /******************* General functions for the class loader *******************/
2724 /******************************************************************************/
2726 /********************* Function: loader_load ***********************************
2728 Loads and links the class desired class and each class and interface
2730 Returns: a pointer to this class
2732 *******************************************************************************/
2734 static int loader_load_running = 0;
2736 classinfo *loader_load (utf *topname)
2740 long int starttime=0,stoptime=0;
2742 /* avoid recursive calls */
2743 if (loader_load_running)
2744 return class_new(topname);
2745 loader_load_running++;
2747 intsDisable(); /* schani */
2750 starttime = getcputime();
2752 top = class_new (topname);
2755 while ( (c = list_first(&unloadedclasses)) ) {
2756 if (!class_load (c)) {
2757 list_remove (&unloadedclasses, c);
2763 while ( (c = list_first(&unlinkedclasses)) ) {
2768 loader_compute_subclasses();
2771 if (getloadingtime) {
2772 stoptime = getcputime();
2773 loadingtime += (stoptime-starttime);
2777 loader_load_running--;
2779 /* check if a former loader_load call tried to load/link the class and failed.
2780 This is needed because the class didn't appear in the undloadclasses or unlinkedclasses list during this class; */
2783 throw_classnotfoundexception2(top->name);
2785 } else if (!top->linked) {
2786 throw_linkageerror2(top->name);
2791 intsRestore(); /* schani */
2797 /**************** function: create_primitive_classes ***************************
2799 create classes representing primitive types
2801 ********************************************************************************/
2804 void create_primitive_classes()
2808 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2809 /* create primitive class */
2810 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2811 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2812 c -> impldBy = NULL;
2814 /* prevent loader from loading primitive class */
2815 list_remove (&unloadedclasses, c);
2817 /* add to unlinked classes */
2818 list_addlast (&unlinkedclasses, c);
2819 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
2822 primitivetype_table[i].class_primitive = c;
2824 /* create class for wrapping the primitive type */
2825 primitivetype_table[i].class_wrap =
2826 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2827 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2828 primitivetype_table[i].class_wrap -> impldBy = NULL;
2830 /* create the primitive array class */
2831 if (primitivetype_table[i].arrayname) {
2832 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2833 primitivetype_table[i].arrayclass = c;
2835 if (!c->linked) class_link(c);
2836 primitivetype_table[i].arrayvftbl = c->vftbl;
2841 /**************** function: class_primitive_from_sig ***************************
2843 return the primitive class indicated by the given signature character
2845 If the descriptor does not indicate a valid primitive type the
2846 return value is NULL.
2848 ********************************************************************************/
2850 classinfo *class_primitive_from_sig(char sig)
2853 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
2854 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
2855 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
2856 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
2857 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
2858 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
2859 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
2860 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
2861 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
2866 /****************** function: class_from_descriptor ****************************
2868 return the class indicated by the given descriptor
2870 utf_ptr....first character of descriptor
2871 end_ptr....first character after the end of the string
2872 next.......if non-NULL, *next is set to the first character after
2874 mode.......what to do if a class descriptor is parsed successfully:
2875 CLASSLOAD_SKIP...skip it and return something != NULL
2876 CLASSLOAD_NEW....get classinfo * via class_new
2877 CLASSLOAD_LOAD...get classinfo * via loader_load
2879 If the descriptor is invalid the return value is NULL
2881 ********************************************************************************/
2883 classinfo *class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
2885 char *start = utf_ptr;
2889 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
2890 if (error) return NULL;
2891 if (next) *next = utf_ptr;
2899 if (mode == CLASSLOAD_SKIP) return class_java_lang_Object;
2900 name = utf_new(start,utf_ptr-start);
2901 return (mode == CLASSLOAD_LOAD) ? loader_load(name) : class_new(name);
2903 return class_primitive_from_sig(*start);
2907 /*************** function: create_pseudo_classes *******************************
2909 create pseudo classes used by the typechecker
2911 ********************************************************************************/
2914 create_pseudo_classes()
2916 /* pseudo class for Arraystubs (extends java.lang.Object) */
2918 pseudo_class_Arraystub = class_new( utf_new_char("$ARRAYSTUB$") );
2919 list_remove(&unloadedclasses,pseudo_class_Arraystub);
2921 pseudo_class_Arraystub->super = class_java_lang_Object;
2922 pseudo_class_Arraystub->interfacescount = 2;
2923 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
2924 pseudo_class_Arraystub->interfaces[0] =
2925 class_java_lang_Cloneable;
2926 pseudo_class_Arraystub->interfaces[1] =
2927 class_java_io_Serializable;
2929 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
2930 class_link(pseudo_class_Arraystub);
2932 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
2934 /* pseudo class representing the null type */
2936 pseudo_class_Null = class_new( utf_new_char("$NULL$") );
2937 list_remove(&unloadedclasses,pseudo_class_Null);
2939 pseudo_class_Null->super = class_java_lang_Object;
2941 list_addlast(&unlinkedclasses,pseudo_class_Null);
2942 class_link(pseudo_class_Null);
2945 /********************** Function: loader_init **********************************
2947 Initializes all lists and loads all classes required for the system or the
2950 *******************************************************************************/
2952 void loader_init (u1 * stackbottom)
2957 log_text("Entering loader_init");
2960 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2961 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2962 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2964 /* create utf-symbols for pointer comparison of frequently used strings */
2965 utf_innerclasses = utf_new_char("InnerClasses");
2966 utf_constantvalue = utf_new_char("ConstantValue");
2967 utf_code = utf_new_char("Code");
2968 utf_finalize = utf_new_char("finalize");
2969 utf_fidesc = utf_new_char("()V");
2970 utf_clinit = utf_new_char("<clinit>");
2971 utf_initsystemclass = utf_new_char("initializeSystemClass");
2972 utf_systemclass = utf_new_char("java/lang/System");
2973 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
2974 utf_initialize =utf_new_char("initialize");
2975 utf_initializedesc =utf_new_char("(I)V");
2977 utf_vmclass =utf_new_char("java/lang/VMClass");
2979 /* create some important classes */
2980 /* These classes have to be created now because the classinfo
2981 * pointers are used in the loading code.
2983 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
2984 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
2985 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
2986 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
2988 log_text("loader_init: java/lang/Object");
2989 /* load the classes which were created above */
2990 loader_load (class_java_lang_Object->name);
2992 loader_inited=1; /*JOWENN*/
2994 class_java_lang_Throwable =
2995 loader_load( utf_new_char("java/lang/Throwable") );
2997 log_text("loader_init: loader_load: java/lang/ClassCastException");
2998 class_java_lang_ClassCastException =
2999 loader_load ( utf_new_char ("java/lang/ClassCastException") );
3000 class_java_lang_NullPointerException =
3001 loader_load ( utf_new_char ("java/lang/NullPointerException") );
3002 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
3003 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
3004 class_java_lang_NegativeArraySizeException = loader_load (
3005 utf_new_char ("java/lang/NegativeArraySizeException") );
3006 class_java_lang_OutOfMemoryError = loader_load (
3007 utf_new_char ("java/lang/OutOfMemoryError") );
3008 class_java_lang_ArrayStoreException =
3009 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
3010 class_java_lang_ArithmeticException =
3011 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
3012 class_java_lang_ThreadDeath = /* schani */
3013 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
3014 /* create classes representing primitive types */
3015 create_primitive_classes();
3017 /* create classes used by the typechecker */
3018 create_pseudo_classes();
3020 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3021 stringtable_update();
3029 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3030 proto_java_lang_ClassCastException =
3031 builtin_new(class_java_lang_ClassCastException);
3032 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3034 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3036 proto_java_lang_NullPointerException =
3037 builtin_new(class_java_lang_NullPointerException);
3038 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3039 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3041 proto_java_lang_ArrayIndexOutOfBoundsException =
3042 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3043 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3045 proto_java_lang_NegativeArraySizeException =
3046 builtin_new(class_java_lang_NegativeArraySizeException);
3047 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3049 proto_java_lang_OutOfMemoryError =
3050 builtin_new(class_java_lang_OutOfMemoryError);
3051 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3053 proto_java_lang_ArithmeticException =
3054 builtin_new(class_java_lang_ArithmeticException);
3055 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3057 proto_java_lang_ArrayStoreException =
3058 builtin_new(class_java_lang_ArrayStoreException);
3059 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3061 proto_java_lang_ThreadDeath = /* schani */
3062 builtin_new(class_java_lang_ThreadDeath);
3063 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3072 /********************* Function: loader_initclasses ****************************
3074 Initializes all loaded but uninitialized classes
3076 *******************************************************************************/
3078 void loader_initclasses ()
3082 intsDisable(); /* schani */
3084 if (makeinitializations) {
3085 c = list_first (&linkedclasses);
3088 c = list_next (&linkedclasses, c);
3092 intsRestore(); /* schani */
3095 static s4 classvalue;
3097 static void loader_compute_class_values (classinfo *c)
3101 c->vftbl->baseval = ++classvalue;
3104 while (subs != NULL) {
3105 loader_compute_class_values(subs);
3106 subs = subs->nextsub;
3108 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3113 for (i = 0; i < c->index; i++)
3115 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3116 utf_display(c->name);
3124 void loader_compute_subclasses ()
3128 intsDisable(); /* schani */
3130 c = list_first (&linkedclasses);
3132 if (!(c->flags & ACC_INTERFACE)) {
3136 c = list_next (&linkedclasses, c);
3139 c = list_first (&linkedclasses);
3141 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3142 c->nextsub = c->super->sub;
3145 c = list_next (&linkedclasses, c);
3148 loader_compute_class_values(class_java_lang_Object);
3150 intsRestore(); /* schani */
3155 /******************** function classloader_buffer ******************************
3157 sets buffer for reading classdata
3159 *******************************************************************************/
3161 void classload_buffer(u1 *buf, int len)
3164 classbuffer_size = len;
3165 classbuf_pos = buf - 1;
3169 /******************** Function: loader_close ***********************************
3173 *******************************************************************************/
3175 void loader_close ()
3179 while ( (c=list_first(&unloadedclasses)) ) {
3180 list_remove (&unloadedclasses,c);
3183 while ( (c=list_first(&unlinkedclasses)) ) {
3184 list_remove (&unlinkedclasses,c);
3187 while ( (c=list_first(&linkedclasses)) ) {
3188 list_remove (&linkedclasses,c);
3195 * These are local overrides for various environment variables in Emacs.
3196 * Please do not remove this and leave it at the end of the file, where
3197 * Emacs will automagically detect them.
3198 * ---------------------------------------------------------------------
3201 * indent-tabs-mode: t