1 /* loader.c - class loader functions
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
28 Changes: Andreas Krall
32 $Id: loader.c 664 2003-11-21 18:24:01Z jowenn $
47 #include "toolbox/memory.h"
48 #include "toolbox/loging.h"
49 #include "threads/thread.h"
60 /* global variables ***********************************************************/
62 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
63 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
64 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
66 int count_class_infos = 0; /* variables for measurements */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
75 bool loadverbose = false; /* switches for debug messages */
76 bool linkverbose = false;
77 bool initverbose = false;
79 bool makeinitializations = true;
81 bool getloadingtime = false; /* to measure the runtime */
82 long int loadingtime = 0;
84 static s4 interfaceindex; /* sequential numbering of interfaces */
86 list unloadedclasses; /* list of all referenced but not loaded classes */
87 list unlinkedclasses; /* list of all loaded but not linked classes */
88 list linkedclasses; /* list of all completely linked classes */
91 /* utf-symbols for pointer comparison of frequently used strings */
93 static utf *utf_innerclasses; /* InnerClasses */
94 static utf *utf_constantvalue; /* ConstantValue */
95 static utf *utf_code; /* Code */
96 static utf *utf_finalize; /* finalize */
97 static utf *utf_fidesc; /* ()V changed */
98 static utf *utf_clinit; /* <clinit> */
99 static utf *utf_initsystemclass; /* initializeSystemClass */
100 static utf *utf_systemclass; /* java/lang/System */
101 static utf *utf_vmclassloader; /*java/lang/VMClassLoader*/
102 static utf *utf_vmclass; /*java/lang/VMClassLoader*/
103 static utf *utf_initialize;
104 static utf *utf_initializedesc;
112 /* important system classes ***************************************************/
114 classinfo *class_java_lang_Object;
115 classinfo *class_java_lang_String;
117 classinfo *class_java_lang_Throwable;
118 classinfo *class_java_lang_Cloneable;
119 classinfo *class_java_io_Serializable;
121 /* Pseudo classes for the typechecker */
122 classinfo *pseudo_class_Arraystub = NULL;
123 classinfo *pseudo_class_Null = NULL;
124 vftbl *pseudo_class_Arraystub_vftbl = NULL;
127 /* These are made static so they cannot be used for throwing in native */
129 static classinfo *class_java_lang_ClassCastException;
130 static classinfo *class_java_lang_NullPointerException;
131 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
132 static classinfo *class_java_lang_NegativeArraySizeException;
133 static classinfo *class_java_lang_OutOfMemoryError;
134 static classinfo *class_java_lang_ArithmeticException;
135 static classinfo *class_java_lang_ArrayStoreException;
136 static classinfo *class_java_lang_ThreadDeath;
138 static methodinfo method_clone_array;
140 static int loader_inited = 0;
142 /******************************************************************************
144 structure for primitive classes: contains the class for wrapping the
145 primitive type, the primitive class, the name of the class for wrapping,
146 the one character type signature and the name of the primitive class
148 ******************************************************************************/
150 /* CAUTION: Don't change the order of the types. This table is indexed
151 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
153 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
154 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
155 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
156 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
157 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
158 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
159 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
160 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
161 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
162 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }};
164 /* instances of important system classes **************************************/
166 java_objectheader *proto_java_lang_ClassCastException;
167 java_objectheader *proto_java_lang_NullPointerException;
168 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
169 java_objectheader *proto_java_lang_NegativeArraySizeException;
170 java_objectheader *proto_java_lang_OutOfMemoryError;
171 java_objectheader *proto_java_lang_ArithmeticException;
172 java_objectheader *proto_java_lang_ArrayStoreException;
173 java_objectheader *proto_java_lang_ThreadDeath;
177 void override_array_class(classinfo *c) {
180 utf *u=utf_new_char("clone");
182 class_showmethods(c);
184 for (i=0;i<sup->methodscount;i++) {
185 if (sup->methods[i].name==u) {
186 method_clone_array.class = c;
187 method_clone_array. flags = ACC_PUBLIC;
188 method_clone_array.name = utf_new_char("clone");
189 method_clone_array.descriptor = utf_new_char("()Ljava/lang/Object;");
191 method_clone_array.jcode = NULL;
192 method_clone_array.exceptiontable = NULL;
193 method_clone_array.entrypoint = NULL;
194 method_clone_array.mcode = NULL;
195 method_clone_array.stubroutine = NULL;
196 method_clone_array.methodUsed = NOTUSED;
197 method_clone_array.monoPoly = MONO;
198 method_clone_array.subRedefs = 0;
199 method_clone_array.subRedefsUsed = 0;
200 method_clone_array.flags=0;
201 method_clone_array.xta = NULL;
202 method_clone_array.stubroutine = createnativestub (&builtin_clone_array, &method_clone_array);
203 c->vftbl->table[sup->methods[i].vftblindex]=method_clone_array.stubroutine;
204 log_text("Found !!!! :)))))))))))))))))))))))))))))))))))))))))))))))))");
220 /************* functions for reading classdata *********************************
222 getting classdata in blocks of variable size
223 (8,16,32,64-bit integer or float)
225 *******************************************************************************/
227 static char *classpath = ""; /* searchpath for classfiles */
228 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
229 static u1 *classbuf_pos; /* current position in classfile buffer */
230 static int classbuffer_size; /* size of classfile-data */
232 /* transfer block of classfile data into a buffer */
234 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
237 /* skip block of classfile data */
239 #define skip_nbytes(len) classbuf_pos+=len;
243 return *++classbuf_pos;
247 u1 a=suck_u1(), b=suck_u1();
248 return ((u2)a<<8)+(u2)b;
252 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
253 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
255 #define suck_s8() (s8) suck_u8()
256 #define suck_s2() (s2) suck_u2()
257 #define suck_s4() (s4) suck_u4()
258 #define suck_s1() (s1) suck_u1()
261 /* get u8 from classfile data */
269 return (hi<<32) + lo;
278 /* get float from classfile data */
280 static float suck_float ()
287 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
288 memcpy ( (u1*) (&f), buffer, 4);
290 suck_nbytes ( (u1*) (&f), 4 );
293 PANICIF (sizeof(float) != 4, "Incompatible float-format");
298 /* get double from classfile data */
299 static double suck_double ()
306 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
307 memcpy ( (u1*) (&d), buffer, 8);
309 suck_nbytes ( (u1*) (&d), 8 );
312 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
317 /************************** function suck_init *********************************
319 called once at startup, sets the searchpath for the classfiles
321 *******************************************************************************/
323 void suck_init (char *cpath)
330 /************************** function suck_start ********************************
332 returns true if classbuffer is already loaded or a file for the
333 specified class has succussfully been read in. All directories of
334 the searchpath are used to find the classfile (<classname>.class).
335 Returns false if no classfile is found and writes an error message.
337 *******************************************************************************/
340 bool suck_start (utf *classname) {
342 #define MAXFILENAME 1000 /* maximum length of a filename */
344 char filename[MAXFILENAME+10]; /* room for '.class' */
345 char *pathpos; /* position in searchpath */
346 char c, *utf_ptr; /* pointer to the next utf8-character */
348 int filenamelen, err;
352 if (classbuffer) /* classbuffer is already valid */
359 /* skip path separator */
361 while (*pathpos == ':')
364 /* extract directory from searchpath */
367 while ((*pathpos) && (*pathpos!=':')) {
368 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
369 filename[filenamelen++] = *(pathpos++);
374 if ( ((filename[filenamelen-1]=='p') || (filename[filenamelen-1]=='P')) &
375 ((filename[filenamelen-2]=='i') || (filename[filenamelen-1]=='I')) &
376 ((filename[filenamelen-3]=='z') || (filename[filenamelen-1]=='Z')) ) {
386 filename[filenamelen++]='\0';
387 uf=unzOpen(filename);
389 utf_ptr = classname->text;
391 while (utf_ptr < utf_end(classname)) {
392 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
394 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
396 filename[filenamelen++] = c;
398 strcpy (filename+filenamelen, ".class");
399 /*log_text(filename);*/
400 if (unzLocateFile(uf,filename,1 /*case sensitive*/)==UNZ_OK) {
401 unz_file_info file_info;
402 log_text("Class found in zip file");
403 if (unzGetCurrentFileInfo(uf,&file_info,filename,
404 sizeof(filename),NULL,0,NULL,0) ==UNZ_OK) {
405 if (unzOpenCurrentFile(uf)==UNZ_OK) {
406 classbuffer_size = file_info.uncompressed_size;
407 classbuffer = MNEW(u1, classbuffer_size);
408 classbuf_pos = classbuffer-1;
409 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
410 if (unzReadCurrentFile(uf,classbuffer,classbuffer_size)==classbuffer_size) {
411 unzCloseCurrentFile(uf);
414 MFREE(classbuffer,u1,classbuffer_size);
415 log_text("Error while unzipping");
417 } else log_text("Error while opening file in archive");
418 } else log_text("Error while retrieving fileinfo");
420 unzCloseCurrentFile(uf);
425 filename[filenamelen++] = '/';
427 /* add classname to filename */
429 utf_ptr = classname->text;
430 while (utf_ptr < utf_end(classname)) {
431 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
433 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
435 filename[filenamelen++] = c;
440 strcpy (filename+filenamelen, ".class");
442 classfile = fopen(filename, "r");
443 if (classfile) { /* file exists */
447 sprintf(logtext,"Opening file: %s",filename);
451 /* determine size of classfile */
453 err = stat (filename, &buffer);
455 if (!err) { /* read classfile data */
456 classbuffer_size = buffer.st_size;
457 classbuffer = MNEW(u1, classbuffer_size);
458 classbuf_pos = classbuffer-1;
459 fread(classbuffer, 1, classbuffer_size, classfile);
467 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
475 /************************** function suck_stop *********************************
477 frees memory for buffer with classfile data.
478 Caution: this function may only be called if buffer has been allocated
479 by suck_start with reading a file
481 *******************************************************************************/
485 /* determine amount of classdata not retrieved by suck-operations */
487 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
489 if (classdata_left > 0) {
491 sprintf (logtext,"There are %d access bytes at end of classfile",
498 MFREE(classbuffer, u1, classbuffer_size);
502 /******************************************************************************/
503 /******************* Some support functions ***********************************/
504 /******************************************************************************/
508 void fprintflags (FILE *fp, u2 f)
510 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
511 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
512 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
513 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
514 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
515 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
516 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
517 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
518 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
519 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
520 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
523 /********** internal function: printflags (only for debugging) ***************/
524 void printflags (u2 f)
526 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
527 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
528 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
529 if ( f & ACC_STATIC ) printf (" STATIC");
530 if ( f & ACC_FINAL ) printf (" FINAL");
531 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
532 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
533 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
534 if ( f & ACC_NATIVE ) printf (" NATIVE");
535 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
536 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
540 /************************* Function: skipattribute *****************************
542 skips a (1) 'attribute' structure in the class file
544 *******************************************************************************/
546 static void skipattribute ()
549 skip_nbytes(suck_u4());
552 /********************** Function: skipattributebody ****************************
554 skips an attribute after the 16 bit reference to attribute_name has already
557 *******************************************************************************/
559 static void skipattributebody ()
561 skip_nbytes(suck_u4());
564 /************************* Function: skipattributes ****************************
566 skips num attribute structures
568 *******************************************************************************/
570 static void skipattributes (u4 num)
573 for (i = 0; i < num; i++)
577 /******************** function: innerclass_getconstant ************************
579 like class_getconstant, but if cptags is ZERO null is returned
581 *******************************************************************************/
583 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
585 /* invalid position in constantpool */
586 if (pos >= c->cpcount)
587 panic ("Attempt to access constant outside range");
589 /* constantpool entry of type 0 */
593 /* check type of constantpool entry */
594 if (c->cptags[pos] != ctype) {
595 sprintf (logtext, "Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
596 (int) ctype, (int) c->cptags[pos] );
600 return c->cpinfos[pos];
603 /************************ function: attribute_load ****************************
605 read attributes from classfile
607 *******************************************************************************/
609 static void attribute_load (u4 num, classinfo *c)
613 for (i = 0; i < num; i++) {
614 /* retrieve attribute name */
615 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
617 if ( aname == utf_innerclasses) {
618 /* innerclasses attribute */
620 /* skip attribute length */
622 /* number of records */
623 c->innerclasscount = suck_u2();
624 /* allocate memory for innerclass structure */
625 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
627 for (j=0;j<c->innerclasscount;j++) {
629 /* The innerclass structure contains a class with an encoded name,
630 its defining scope, its simple name and a bitmask of the access flags.
631 If an inner class is not a member, its outer_class is NULL,
632 if a class is anonymous, its name is NULL. */
634 innerclassinfo *info = c->innerclass + j;
636 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
637 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
638 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
639 info->flags = suck_u2 (); /* access_flags bitmask */
642 /* unknown attribute */
643 skipattributebody ();
648 /******************* function: checkfielddescriptor ****************************
650 checks whether a field-descriptor is valid and aborts otherwise
651 all referenced classes are inserted into the list of unloaded classes
653 *******************************************************************************/
655 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
657 char *tstart; /* pointer to start of classname */
659 char *start = utf_ptr; /* XXX remove */
661 switch (*utf_ptr++) {
675 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
676 panic ("Ill formed descriptor");
680 panic ("Ill formed descriptor");
683 /* exceeding characters */
684 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
688 /******************* function checkmethoddescriptor ****************************
690 checks whether a method-descriptor is valid and aborts otherwise.
691 All referenced classes are inserted into the list of unloaded classes.
693 *******************************************************************************/
695 static void checkmethoddescriptor (utf *d)
697 char *utf_ptr = d->text; /* current position in utf text */
698 char *end_pos = utf_end(d); /* points behind utf string */
699 char *tstart; /* pointer to start of classname */
701 char *start; /* XXX remove */
703 /* method descriptor must start with parenthesis */
704 /* XXX check length */
705 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
707 /* XXX check length */
708 /* check arguments */
709 while ((c = *utf_ptr++) != ')') {
710 start = utf_ptr-1; /* XXX remove */
726 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
727 panic ("Ill formed method descriptor");
731 panic ("Ill formed methodtype-descriptor");
735 /* check returntype */
737 /* returntype void */
738 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
741 /* treat as field-descriptor */
742 checkfielddescriptor (utf_ptr,end_pos);
746 /******************** Function: buildarraydescriptor ***************************
748 creates a constant_arraydescriptor structure for the array type named by an
751 *******************************************************************************/
755 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
757 constant_arraydescriptor *d;
759 /* class_new( utf_new(utf_ptr,namelen) ); */ /* XXX remove */
761 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
763 d = NEW (constant_arraydescriptor);
764 d -> objectclass = NULL;
765 d -> elementdescriptor = NULL;
768 count_const_pool_len += sizeof(constant_arraydescriptor);
772 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
773 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
774 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
775 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
776 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
777 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
778 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
779 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
782 d -> arraytype = ARRAYTYPE_ARRAY;
783 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
787 d -> arraytype = ARRAYTYPE_OBJECT;
789 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
790 d -> objectclass -> classUsed = NOTUSED; /* not used initially CO-RT */
791 d -> objectclass -> impldBy = NULL;
799 /******************* Function: freearraydescriptor *****************************
801 removes a structure created by buildarraydescriptor from memory
803 *******************************************************************************/
807 static void freearraydescriptor (constant_arraydescriptor *d)
810 constant_arraydescriptor *n = d->elementdescriptor;
811 FREE (d, constant_arraydescriptor);
817 /*********************** Function: displayarraydescriptor *********************/
821 static void displayarraydescriptor (constant_arraydescriptor *d)
823 switch (d->arraytype) {
824 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
825 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
826 case ARRAYTYPE_CHAR: printf ("char[]"); break;
827 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
828 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
829 case ARRAYTYPE_INT: printf ("int[]"); break;
830 case ARRAYTYPE_LONG: printf ("long[]"); break;
831 case ARRAYTYPE_SHORT: printf ("short[]"); break;
832 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
833 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
838 /***************** Function: print_arraydescriptor ****************************
840 Debugging helper for displaying an arraydescriptor
842 *******************************************************************************/
845 print_arraydescriptor(FILE *file,arraydescriptor *desc)
848 fprintf(file,"<NULL>");
853 if (desc->componentvftbl) {
854 if (desc->componentvftbl->class)
855 utf_fprint(file,desc->componentvftbl->class->name);
857 fprintf(file,"<no classinfo>");
863 if (desc->elementvftbl) {
864 if (desc->elementvftbl->class)
865 utf_fprint(file,desc->elementvftbl->class->name);
867 fprintf(file,"<no classinfo>");
871 fprintf(file,",%d,%d,%d,%d}",desc->arraytype,desc->dimension,
872 desc->dataoffset,desc->componentsize);
875 /******************************************************************************/
876 /************************** Functions for fields ****************************/
877 /******************************************************************************/
880 /************************ Function: field_load *********************************
882 Load everything about a class field from the class file and fill a
883 'fieldinfo' structure. For static fields, space in the data segment is
886 *******************************************************************************/
888 static void field_load (fieldinfo *f, classinfo *c)
893 f -> flags = suck_u2 (); /* ACC flags */
894 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
895 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
896 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
897 f -> offset = 0; /* offset from start of object */
901 case TYPE_INT: f->value.i = 0; break;
902 case TYPE_FLOAT: f->value.f = 0.0; break;
903 case TYPE_DOUBLE: f->value.d = 0.0; break;
904 case TYPE_ADDRESS: f->value.a = NULL;
905 heap_addreference (&(f->value.a)); /* make global reference (GC) */
909 f->value.l = 0; break;
911 f->value.l.low = 0; f->value.l.high = 0; break;
915 /* read attributes */
917 for (i=0; i<attrnum; i++) {
921 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
923 if ( aname != utf_constantvalue ) {
924 /* unknown attribute */
925 skipattributebody ();
928 /* constant value attribute */
930 /* skip attribute length */
932 /* index of value in constantpool */
935 /* initialize field with value from constantpool */
938 constant_integer *ci =
939 class_getconstant(c, pindex, CONSTANT_Integer);
940 f->value.i = ci -> value;
946 class_getconstant(c, pindex, CONSTANT_Long);
948 f->value.l = cl -> value;
954 class_getconstant(c, pindex, CONSTANT_Float);
956 f->value.f = cf->value;
961 constant_double *cd =
962 class_getconstant(c, pindex, CONSTANT_Double);
964 f->value.d = cd->value;
969 utf *u = class_getconstant(c, pindex, CONSTANT_String);
970 /* create javastring from compressed utf8-string */
971 f->value.a = literalstring_new(u);
976 log_text ("Invalid Constant - Type");
985 /********************** function: field_free **********************************/
987 static void field_free (fieldinfo *f)
993 /**************** Function: field_display (debugging only) ********************/
995 void field_display (fieldinfo *f)
998 printflags (f -> flags);
1000 utf_display (f -> name);
1002 utf_display (f -> descriptor);
1003 printf (" offset: %ld\n", (long int) (f -> offset) );
1007 /******************************************************************************/
1008 /************************* Functions for methods ******************************/
1009 /******************************************************************************/
1012 /*********************** Function: method_load *********************************
1014 Loads a method from the class file and fills an existing 'methodinfo'
1015 structure. For native methods, the function pointer field is set to the
1016 real function pointer, for JavaVM methods a pointer to the compiler is used
1019 *******************************************************************************/
1021 static void method_load (methodinfo *m, classinfo *c)
1026 count_all_methods++;
1031 m -> flags = suck_u2 ();
1032 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
1033 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
1036 m -> exceptiontable = NULL;
1037 m -> entrypoint = NULL;
1039 m -> stubroutine = NULL;
1040 m -> methodUsed = NOTUSED;
1041 m -> monoPoly = MONO;
1043 m -> subRedefsUsed = 0;
1047 if (! (m->flags & ACC_NATIVE) ) {
1048 m -> stubroutine = createcompilerstub (m);
1052 functionptr f = native_findfunction
1053 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
1055 m -> stubroutine = createnativestub (f, m);
1060 attrnum = suck_u2();
1061 for (i=0; i<attrnum; i++) {
1064 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
1066 if ( aname != utf_code) {
1067 skipattributebody ();
1070 if (m -> jcode) panic ("Two code-attributes for one method!");
1073 m -> maxstack = suck_u2();
1074 m -> maxlocals = suck_u2();
1075 m -> jcodelength = suck_u4();
1076 m -> jcode = MNEW (u1, m->jcodelength);
1077 suck_nbytes (m->jcode, m->jcodelength);
1078 m -> exceptiontablelength = suck_u2 ();
1079 m -> exceptiontable =
1080 MNEW (exceptiontable, m->exceptiontablelength);
1083 count_vmcode_len += m->jcodelength + 18;
1084 count_extable_len += 8 * m->exceptiontablelength;
1087 for (e=0; e < m->exceptiontablelength; e++) {
1089 m -> exceptiontable[e].startpc = suck_u2();
1090 m -> exceptiontable[e].endpc = suck_u2();
1091 m -> exceptiontable[e].handlerpc = suck_u2();
1094 if (!idx) m -> exceptiontable[e].catchtype = NULL;
1096 m -> exceptiontable[e].catchtype =
1097 class_getconstant (c, idx, CONSTANT_Class);
1101 skipattributes ( suck_u2() );
1108 /********************* Function: method_free ***********************************
1110 frees all memory that was allocated for this method
1112 *******************************************************************************/
1114 static void method_free (methodinfo *m)
1116 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1117 if (m->exceptiontable)
1118 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1119 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1120 if (m->stubroutine) {
1121 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1122 else removecompilerstub (m->stubroutine);
1127 /************** Function: method_display (debugging only) **************/
1129 void method_display (methodinfo *m)
1132 printflags (m -> flags);
1134 utf_display (m -> name);
1136 utf_display (m -> descriptor);
1141 /******************** Function: method_canoverwrite ****************************
1143 Check if m and old are identical with respect to type and name. This means
1144 that old can be overwritten with m.
1146 *******************************************************************************/
1148 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1150 if (m->name != old->name) return false;
1151 if (m->descriptor != old->descriptor) return false;
1152 if (m->flags & ACC_STATIC) return false;
1159 /******************************************************************************/
1160 /************************ Functions for class *********************************/
1161 /******************************************************************************/
1164 /******************** function:: class_getconstant ******************************
1166 retrieves the value at position 'pos' of the constantpool of a class
1167 if the type of the value is other than 'ctype' the system is stopped
1169 *******************************************************************************/
1171 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1173 /* invalid position in constantpool */
1174 if (pos >= c->cpcount)
1175 panic ("Attempt to access constant outside range");
1177 /* check type of constantpool entry */
1179 if (c->cptags[pos] != ctype) {
1180 class_showconstantpool(c);
1181 sprintf (logtext, "Type mismatch on constant: %d requested, %d here (class_getconstant)",
1182 (int) ctype, (int) c->cptags[pos] );
1186 return c->cpinfos[pos];
1190 /********************* Function: class_constanttype ****************************
1192 Determines the type of a class entry in the ConstantPool
1194 *******************************************************************************/
1196 u4 class_constanttype (classinfo *c, u4 pos)
1198 if (pos >= c->cpcount)
1199 panic ("Attempt to access constant outside range");
1200 return c->cptags[pos];
1204 /******************** function: class_loadcpool ********************************
1206 loads the constantpool of a class,
1207 the entries are transformed into a simpler format
1208 by resolving references
1209 (a detailed overview of the compact structures can be found in global.h)
1211 *******************************************************************************/
1213 static void class_loadcpool (classinfo *c)
1216 /* The following structures are used to save information which cannot be
1217 processed during the first pass. After the complete constantpool has
1218 been traversed the references can be resolved.
1219 (only in specific order) */
1221 /* CONSTANT_Class_info entries */
1222 typedef struct forward_class {
1223 struct forward_class *next;
1228 /* CONSTANT_String */
1229 typedef struct forward_string {
1230 struct forward_string *next;
1235 /* CONSTANT_NameAndType */
1236 typedef struct forward_nameandtype {
1237 struct forward_nameandtype *next;
1241 } forward_nameandtype;
1243 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1244 typedef struct forward_fieldmethint {
1245 struct forward_fieldmethint *next;
1249 u2 nameandtype_index;
1250 } forward_fieldmethint;
1254 long int dumpsize = dump_size ();
1256 forward_class *forward_classes = NULL;
1257 forward_string *forward_strings = NULL;
1258 forward_nameandtype *forward_nameandtypes = NULL;
1259 forward_fieldmethint *forward_fieldmethints = NULL;
1261 /* number of entries in the constant_pool table */
1262 u4 cpcount = c -> cpcount = suck_u2();
1263 /* allocate memory */
1264 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1265 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1268 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1271 /* initialize constantpool */
1272 for (idx=0; idx<cpcount; idx++) {
1273 cptags[idx] = CONSTANT_UNUSED;
1274 cpinfos[idx] = NULL;
1278 /******* first pass *******/
1279 /* entries which cannot be resolved now are written into
1280 temporary structures and traversed again later */
1283 while (idx < cpcount) {
1284 /* get constant type */
1288 case CONSTANT_Class: {
1289 forward_class *nfc = DNEW(forward_class);
1291 nfc -> next = forward_classes;
1292 forward_classes = nfc;
1294 nfc -> thisindex = idx;
1295 /* reference to CONSTANT_NameAndType */
1296 nfc -> name_index = suck_u2 ();
1302 case CONSTANT_Fieldref:
1303 case CONSTANT_Methodref:
1304 case CONSTANT_InterfaceMethodref: {
1305 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1307 nff -> next = forward_fieldmethints;
1308 forward_fieldmethints = nff;
1310 nff -> thisindex = idx;
1313 /* class or interface type that contains the declaration of the field or method */
1314 nff -> class_index = suck_u2 ();
1315 /* name and descriptor of the field or method */
1316 nff -> nameandtype_index = suck_u2 ();
1322 case CONSTANT_String: {
1323 forward_string *nfs = DNEW (forward_string);
1325 nfs -> next = forward_strings;
1326 forward_strings = nfs;
1328 nfs -> thisindex = idx;
1329 /* reference to CONSTANT_Utf8_info with string characters */
1330 nfs -> string_index = suck_u2 ();
1336 case CONSTANT_NameAndType: {
1337 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1339 nfn -> next = forward_nameandtypes;
1340 forward_nameandtypes = nfn;
1342 nfn -> thisindex = idx;
1343 /* reference to CONSTANT_Utf8_info containing simple name */
1344 nfn -> name_index = suck_u2 ();
1345 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1346 nfn -> sig_index = suck_u2 ();
1352 case CONSTANT_Integer: {
1353 constant_integer *ci = NEW (constant_integer);
1356 count_const_pool_len += sizeof(constant_integer);
1359 ci -> value = suck_s4 ();
1360 cptags [idx] = CONSTANT_Integer;
1367 case CONSTANT_Float: {
1368 constant_float *cf = NEW (constant_float);
1371 count_const_pool_len += sizeof(constant_float);
1374 cf -> value = suck_float ();
1375 cptags [idx] = CONSTANT_Float;
1381 case CONSTANT_Long: {
1382 constant_long *cl = NEW(constant_long);
1385 count_const_pool_len += sizeof(constant_long);
1388 cl -> value = suck_s8 ();
1389 cptags [idx] = CONSTANT_Long;
1395 case CONSTANT_Double: {
1396 constant_double *cd = NEW(constant_double);
1399 count_const_pool_len += sizeof(constant_double);
1402 cd -> value = suck_double ();
1403 cptags [idx] = CONSTANT_Double;
1409 case CONSTANT_Utf8: {
1411 /* number of bytes in the bytes array (not string-length) */
1412 u4 length = suck_u2();
1413 cptags [idx] = CONSTANT_Utf8;
1414 /* insert utf-string into the utf-symboltable */
1415 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1416 /* skip bytes of the string */
1417 skip_nbytes(length);
1423 sprintf (logtext, "Unkown constant type: %d",(int) t);
1432 /* resolve entries in temporary structures */
1434 while (forward_classes) {
1436 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1438 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1439 /* retrieve class from class-table */
1440 cpinfos [forward_classes -> thisindex] = class_new (name);
1442 forward_classes = forward_classes -> next;
1446 while (forward_strings) {
1448 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1450 log_text("forward_string:");
1451 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1453 log_text("\n------------------"); */
1454 /* resolve utf-string */
1455 cptags [forward_strings -> thisindex] = CONSTANT_String;
1456 cpinfos [forward_strings -> thisindex] = text;
1458 forward_strings = forward_strings -> next;
1461 while (forward_nameandtypes) {
1462 constant_nameandtype *cn = NEW (constant_nameandtype);
1465 count_const_pool_len += sizeof(constant_nameandtype);
1468 /* resolve simple name and descriptor */
1469 cn -> name = class_getconstant
1470 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1471 cn -> descriptor = class_getconstant
1472 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1474 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1475 cpinfos [forward_nameandtypes -> thisindex] = cn;
1477 forward_nameandtypes = forward_nameandtypes -> next;
1481 while (forward_fieldmethints) {
1482 constant_nameandtype *nat;
1483 constant_FMIref *fmi = NEW (constant_FMIref);
1486 count_const_pool_len += sizeof(constant_FMIref);
1488 /* resolve simple name and descriptor */
1489 nat = class_getconstant
1490 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1493 log_text("trying to resolve:");
1494 log_text(nat->name->text);
1495 switch(forward_fieldmethints ->tag) {
1496 case CONSTANT_Fieldref:
1497 log_text("CONSTANT_Fieldref");
1499 case CONSTANT_InterfaceMethodref:
1500 log_text("CONSTANT_InterfaceMethodref");
1502 case CONSTANT_Methodref:
1503 log_text("CONSTANT_Methodref");
1507 fmi -> class = class_getconstant
1508 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1509 fmi -> name = nat -> name;
1510 fmi -> descriptor = nat -> descriptor;
1512 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1513 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1515 switch (forward_fieldmethints -> tag) {
1516 case CONSTANT_Fieldref: /* check validity of descriptor */
1517 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1519 case CONSTANT_InterfaceMethodref:
1520 case CONSTANT_Methodref: /* check validity of descriptor */
1521 checkmethoddescriptor (fmi->descriptor);
1525 forward_fieldmethints = forward_fieldmethints -> next;
1529 /* class_showconstantpool(c); */
1531 dump_release (dumpsize);
1535 /********************** Function: class_load ***********************************
1537 Loads everything interesting about a class from the class file. The
1538 'classinfo' structure must have been allocated previously.
1540 The super class and the interfaces implemented by this class need not be
1541 loaded. The link is set later by the function 'class_link'.
1543 The loaded class is removed from the list 'unloadedclasses' and added to
1544 the list 'unlinkedclasses'.
1546 *******************************************************************************/
1548 static int class_load (classinfo *c)
1554 count_class_loads++;
1558 /* loadverbose = 1; */
1560 /* output for debugging purposes */
1563 sprintf (logtext, "Loading class: ");
1564 utf_sprint (logtext+strlen(logtext), c->name );
1568 /* load classdata, throw exception on error */
1570 if (!suck_start (c->name)) {
1571 throw_classnotfoundexception2(c->name);
1575 /* check signature */
1576 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1580 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1581 sprintf (logtext, "File version %d.%d is not supported",
1582 (int) ma, (int) mi);
1586 class_loadcpool (c);
1588 c->erroneous_state=0;
1589 c->initializing_thread=0;
1591 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1592 c -> impldBy = NULL;
1595 c -> flags = suck_u2 ();
1599 /* retrieve superclass */
1600 if ( (i = suck_u2 () ) ) {
1601 c -> super = class_getconstant (c, i, CONSTANT_Class);
1607 /* retrieve interfaces */
1608 c -> interfacescount = suck_u2 ();
1609 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1610 for (i=0; i < c -> interfacescount; i++) {
1611 c -> interfaces [i] =
1612 class_getconstant (c, suck_u2(), CONSTANT_Class);
1616 c -> fieldscount = suck_u2 ();
1617 /* utf_display(c->name);
1618 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1620 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1621 for (i=0; i < c -> fieldscount; i++) {
1622 field_load (&(c->fields[i]), c);
1626 c -> methodscount = suck_u2 ();
1627 c -> methods = MNEW (methodinfo, c -> methodscount);
1628 for (i=0; i < c -> methodscount; i++) {
1629 method_load (&(c -> methods [i]), c);
1633 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1634 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1635 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1638 /* load variable-length attribute structures */
1639 attribute_load (suck_u2(), c);
1644 /* remove class from list of unloaded classes and
1645 add to list of unlinked classes */
1646 list_remove (&unloadedclasses, c);
1647 list_addlast (&unlinkedclasses, c);
1654 /************** internal Function: class_highestinterface ***********************
1656 Used by the function class_link to determine the amount of memory needed
1657 for the interface table.
1659 *******************************************************************************/
1661 static s4 class_highestinterface (classinfo *c)
1666 if ( ! (c->flags & ACC_INTERFACE) ) {
1667 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1668 utf_sprint (logtext+strlen(logtext), c->name);
1673 for (i=0; i<c->interfacescount; i++) {
1674 s4 h2 = class_highestinterface (c->interfaces[i]);
1681 /* class_addinterface **********************************************************
1683 Is needed by class_link for adding a VTBL to a class. All interfaces
1684 implemented by ic are added as well.
1686 *******************************************************************************/
1688 static void class_addinterface (classinfo *c, classinfo *ic)
1692 vftbl *vftbl = c->vftbl;
1694 if (i >= vftbl->interfacetablelength)
1695 panic ("Inernal error: interfacetable overflow");
1696 if (vftbl->interfacetable[-i])
1699 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1700 vftbl->interfacevftbllength[i] = 1;
1701 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1702 vftbl->interfacetable[-i][0] = NULL;
1705 vftbl->interfacevftbllength[i] = ic->methodscount;
1706 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1709 count_vftbl_len += sizeof(methodptr) *
1710 (ic->methodscount + (ic->methodscount == 0));
1713 for (j=0; j<ic->methodscount; j++) {
1716 for (m = 0; m < sc->methodscount; m++) {
1717 methodinfo *mi = &(sc->methods[m]);
1718 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1719 vftbl->interfacetable[-i][j] =
1720 vftbl->table[mi->vftblindex];
1730 for (j = 0; j < ic->interfacescount; j++)
1731 class_addinterface(c, ic->interfaces[j]);
1735 /******************* Function: class_new_array *********************************
1737 This function is called by class_new to setup an array class.
1739 *******************************************************************************/
1742 class_new_array(classinfo *c)
1744 classinfo *comp = NULL;
1748 /* XXX remove logging */
1750 sprintf(logtext,"new array class: ");
1751 utf_sprint(logtext+strlen(logtext),c->name);
1755 /* Array classes are not loaded from classfiles. */
1756 list_remove (&unloadedclasses, c);
1758 /* Check array class name */
1759 namelen = c->name->blength;
1760 if (namelen < 2 || c->name->text[0] != '[')
1761 panic("Invalid array class name.");
1763 /* Check the component type */
1764 switch (c->name->text[1]) {
1766 /* c is an array of arrays. We have to create the component class. */
1767 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1771 /* XXX remove logging */
1773 sprintf(logtext,"Component class: ");
1774 utf_sprint(logtext+strlen(logtext),utf_new(c->name->text + 2,namelen - 3));
1776 if (class_get(utf_new(c->name->text + 2,namelen - 3)))
1777 log_text("Already created.");
1780 /* c is an array of objects. */
1781 if (namelen < 4 || c->name->text[namelen-1] != ';')
1782 panic("Invalid array class name.");
1783 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1787 /* Setup the array class */
1788 c->super = class_java_lang_Object;
1790 c->interfacescount = 2;
1791 c->interfaces = MNEW(classinfo*,2);
1792 c->interfaces[0] = class_java_lang_Cloneable;
1793 c->interfaces[1] = class_java_io_Serializable;
1795 c->methodscount = 1;
1796 c->methods = MNEW (methodinfo, c->methodscount);
1799 memset(clone,0,sizeof(methodinfo));
1800 clone->flags = ACC_PUBLIC; /* XXX protected? */
1801 clone->name = utf_new_char("clone");
1802 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1804 clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1805 clone->monoPoly = MONO; /* XXX should be poly? */
1807 /* XXX: field: length? */
1809 /* The array class has to be linked */
1810 list_addlast(&unlinkedclasses,c);
1813 * Array classes which are created after the other classes have been
1814 * loaded and linked are linked explicitely.
1817 loader_load(c->name);
1820 /****************** Function: class_link_array *********************************
1822 This function is called by class_link to create the
1823 arraydescriptor for an array class.
1825 This function returns NULL if the array cannot be linked because
1826 the component type has not been linked yet.
1828 *******************************************************************************/
1832 class_link_array(classinfo *c)
1834 classinfo *comp = NULL;
1835 int namelen = c->name->blength;
1836 arraydescriptor *desc;
1839 /* XXX remove logging */
1842 sprintf(logtext,"linking array class: ");
1843 utf_sprint(logtext+strlen(logtext),c->name);
1848 /* Check the component type */
1849 switch (c->name->text[1]) {
1851 /* c is an array of arrays. */
1852 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1853 if (!comp) panic("Could not find component array class.");
1857 /* c is an array of objects. */
1858 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1859 if (!comp) panic("Could not find component class.");
1863 /* If the component type has not been linked return NULL */
1864 if (comp && !comp->linked)
1867 /* Allocate the arraydescriptor */
1868 desc = NEW(arraydescriptor);
1871 /* c is an array of references */
1872 desc->arraytype = ARRAYTYPE_OBJECT;
1873 desc->componentsize = sizeof(void*);
1874 desc->dataoffset = OFFSET(java_objectarray,data);
1876 compvftbl = comp->vftbl;
1878 panic("Component class has no vftbl.");
1879 desc->componentvftbl = compvftbl;
1881 if (compvftbl->arraydesc) {
1882 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1883 desc->dimension = compvftbl->arraydesc->dimension + 1;
1886 desc->elementvftbl = compvftbl;
1887 desc->dimension = 1;
1891 /* c is an array of a primitive type */
1892 switch (c->name->text[1]) {
1893 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1894 desc->dataoffset = OFFSET(java_booleanarray,data);
1895 desc->componentsize = sizeof(u1); break;
1896 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1897 desc->dataoffset = OFFSET(java_bytearray,data);
1898 desc->componentsize = sizeof(u1); break;
1899 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1900 desc->dataoffset = OFFSET(java_chararray,data);
1901 desc->componentsize = sizeof(u2); break;
1902 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1903 desc->dataoffset = OFFSET(java_doublearray,data);
1904 desc->componentsize = sizeof(double); break;
1905 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1906 desc->dataoffset = OFFSET(java_floatarray,data);
1907 desc->componentsize = sizeof(float); break;
1908 case 'I': desc->arraytype = ARRAYTYPE_INT;
1909 desc->dataoffset = OFFSET(java_intarray,data);
1910 desc->componentsize = sizeof(s4); break;
1911 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1912 desc->dataoffset = OFFSET(java_longarray,data);
1913 desc->componentsize = sizeof(s8); break;
1914 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1915 desc->dataoffset = OFFSET(java_shortarray,data);
1916 desc->componentsize = sizeof(s2); break;
1918 panic("Invalid array class name");
1921 desc->componentvftbl = NULL;
1922 desc->elementvftbl = NULL;
1923 desc->dimension = 1;
1926 /* XXX remove logging */
1928 print_arraydescriptor(stdout,desc);
1935 /********************** Function: class_link ***********************************
1937 Tries to link a class. The super class and every implemented interface must
1938 already have been linked. The function calculates the length in bytes that
1939 an instance of this class requires as well as the VTBL for methods and
1942 If the class can be linked, it is removed from the list 'unlinkedclasses'
1943 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1946 Attention: If cyclical class definitions are encountered, the program gets
1947 into an infinite loop (we'll have to work that out)
1949 *******************************************************************************/
1951 void class_link(classinfo *c)
1953 s4 supervftbllength; /* vftbllegnth of super class */
1954 s4 vftbllength; /* vftbllength of current class */
1955 s4 interfacetablelength; /* interface table length */
1956 classinfo *super = c->super; /* super class */
1957 classinfo *ic, *c2; /* intermediate class variables */
1958 vftbl *v; /* vftbl of current class */
1959 s4 i; /* interface/method/field counter */
1960 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
1963 /* XXX remove log */
1965 sprintf(logtext,"trying to link: ");
1966 utf_sprint(logtext+strlen(logtext),c->name);
1970 /* check if all superclasses are already linked, if not put c at end of
1971 unlinked list and return. Additionally initialize class fields. */
1973 /* check interfaces */
1975 for (i = 0; i < c->interfacescount; i++) {
1976 ic = c->interfaces[i];
1978 list_remove(&unlinkedclasses, c);
1979 list_addlast(&unlinkedclasses, c);
1984 /* check super class */
1986 if (super == NULL) { /* class java.long.Object */
1988 c->classUsed = USED; /* Object class is always used CO-RT*/
1989 c -> impldBy = NULL;
1990 c->instancesize = sizeof(java_objectheader);
1992 vftbllength = supervftbllength = 0;
1994 c->finalizer = NULL;
1997 if (!super->linked) {
1998 list_remove(&unlinkedclasses, c);
1999 list_addlast(&unlinkedclasses, c);
2003 /* handle array classes */
2004 if (c->name->text[0] == '[')
2005 if ((arraydesc = class_link_array(c)) == NULL) {
2006 list_remove(&unlinkedclasses, c);
2007 list_addlast(&unlinkedclasses, c);
2011 if (c->flags & ACC_INTERFACE)
2012 c->index = interfaceindex++;
2014 c->index = super->index + 1;
2016 c->instancesize = super->instancesize;
2018 vftbllength = supervftbllength = super->vftbl->vftbllength;
2020 c->finalizer = super->finalizer;
2025 sprintf (logtext, "Linking Class: ");
2026 utf_sprint (logtext+strlen(logtext), c->name );
2030 /* compute vftbl length */
2032 for (i = 0; i < c->methodscount; i++) {
2033 methodinfo *m = &(c->methods[i]);
2035 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2036 classinfo *sc = super;
2039 for (j = 0; j < sc->methodscount; j++) {
2040 if (method_canoverwrite(m, &(sc->methods[j]))) {
2041 m->vftblindex = sc->methods[j].vftblindex;
2042 goto foundvftblindex;
2047 m->vftblindex = (vftbllength++);
2053 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
2056 /* compute interfacetable length */
2058 interfacetablelength = 0;
2061 for (i = 0; i < c2->interfacescount; i++) {
2062 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2063 if (h > interfacetablelength)
2064 interfacetablelength = h;
2069 /* allocate virtual function table */
2071 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2072 (vftbllength - 1) + sizeof(methodptr*) *
2073 (interfacetablelength - (interfacetablelength > 0)));
2074 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2075 (interfacetablelength > 1));
2076 c->header.vftbl = c->vftbl = v;
2078 v->vftbllength = vftbllength;
2079 v->interfacetablelength = interfacetablelength;
2080 v->arraydesc = arraydesc;
2082 /* store interface index in vftbl */
2083 if (c->flags & ACC_INTERFACE)
2084 v->baseval = -(c->index);
2086 /* copy virtual function table of super class */
2088 for (i = 0; i < supervftbllength; i++)
2089 v->table[i] = super->vftbl->table[i];
2091 /* add method stubs into virtual function table */
2093 for (i = 0; i < c->methodscount; i++) {
2094 methodinfo *m = &(c->methods[i]);
2095 if (!(m->flags & ACC_STATIC)) {
2096 v->table[m->vftblindex] = m->stubroutine;
2100 /* compute instance size and offset of each field */
2102 for (i = 0; i < c->fieldscount; i++) {
2104 fieldinfo *f = &(c->fields[i]);
2106 if (!(f->flags & ACC_STATIC) ) {
2107 dsize = desc_typesize (f->descriptor);
2108 c->instancesize = ALIGN (c->instancesize, dsize);
2109 f->offset = c->instancesize;
2110 c->instancesize += dsize;
2114 /* initialize interfacetable and interfacevftbllength */
2116 v->interfacevftbllength = MNEW (s4, interfacetablelength);
2119 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2122 for (i = 0; i < interfacetablelength; i++) {
2123 v->interfacevftbllength[i] = 0;
2124 v->interfacetable[-i] = NULL;
2127 /* add interfaces */
2129 for (c2 = c; c2 != NULL; c2 = c2->super)
2130 for (i = 0; i < c2->interfacescount; i++) {
2131 class_addinterface (c, c2->interfaces[i]);
2134 /* add finalizer method (not for java.lang.Object) */
2136 if (super != NULL) {
2138 static utf *finame = NULL;
2139 static utf *fidesc = NULL;
2142 finame = utf_finalize;
2144 fidesc = utf_fidesc;
2146 fi = class_findmethod (c, finame, fidesc);
2148 if (!(fi->flags & ACC_STATIC)) {
2158 list_remove (&unlinkedclasses, c);
2159 list_addlast (&linkedclasses, c);
2164 /******************* Function: class_freepool **********************************
2166 Frees all resources used by this classes Constant Pool.
2168 *******************************************************************************/
2170 static void class_freecpool (classinfo *c)
2176 for (idx=0; idx < c->cpcount; idx++) {
2177 tag = c->cptags[idx];
2178 info = c->cpinfos[idx];
2182 case CONSTANT_Fieldref:
2183 case CONSTANT_Methodref:
2184 case CONSTANT_InterfaceMethodref:
2185 FREE (info, constant_FMIref);
2187 case CONSTANT_Integer:
2188 FREE (info, constant_integer);
2190 case CONSTANT_Float:
2191 FREE (info, constant_float);
2194 FREE (info, constant_long);
2196 case CONSTANT_Double:
2197 FREE (info, constant_double);
2199 case CONSTANT_NameAndType:
2200 FREE (info, constant_nameandtype);
2206 MFREE (c -> cptags, u1, c -> cpcount);
2207 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2211 /*********************** Function: class_free **********************************
2213 Frees all resources used by the class.
2215 *******************************************************************************/
2217 static void class_free (classinfo *c)
2222 class_freecpool (c);
2224 MFREE (c->interfaces, classinfo*, c->interfacescount);
2226 for (i = 0; i < c->fieldscount; i++)
2227 field_free(&(c->fields[i]));
2229 for (i = 0; i < c->methodscount; i++)
2230 method_free(&(c->methods[i]));
2231 MFREE (c->methods, methodinfo, c->methodscount);
2233 if ((v = c->vftbl) != NULL) {
2235 mem_free(v->arraydesc,sizeof(arraydescriptor));
2237 for (i = 0; i < v->interfacetablelength; i++) {
2238 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2240 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2242 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2243 sizeof(methodptr*) * (v->interfacetablelength -
2244 (v->interfacetablelength > 0));
2245 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2246 (v->interfacetablelength > 1));
2250 if (c->innerclasscount)
2251 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2253 /* if (c->classvftbl)
2254 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2256 FREE (c, classinfo);
2259 /************************* Function: class_findfield ***************************
2261 Searches a 'classinfo' structure for a field having the given name and
2264 *******************************************************************************/
2267 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2272 for (i = 0; i < c->fieldscount; i++) {
2273 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2274 return &(c->fields[i]);
2277 panic ("Can not find field given in CONSTANT_Fieldref");
2282 /************************* Function: class_findmethod **************************
2284 Searches a 'classinfo' structure for a method having the given name and
2285 type and returns the index in the class info structure.
2286 If type is NULL, it is ignored.
2288 *******************************************************************************/
2290 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2293 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2295 int buffer_len, pos;
2297 #ifdef JOWENN_DEBUG1
2300 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2302 buffer = MNEW(char, buffer_len);
2304 strcpy(buffer, "class_findmethod: method:");
2305 utf_sprint(buffer+strlen(buffer), name);
2306 strcpy(buffer+strlen(buffer), ", desc: ");
2307 utf_sprint(buffer+strlen(buffer), desc);
2308 strcpy(buffer+strlen(buffer), ", classname: ");
2309 utf_sprint(buffer+strlen(buffer), c->name);
2313 MFREE(buffer, char, buffer_len);
2315 for (i = 0; i < c->methodscount; i++) {
2316 #ifdef JOWENN_DEBUG2
2318 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2320 buffer = MNEW(char, buffer_len);
2322 strcpy(buffer, "class_findmethod: comparing to method:");
2323 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2324 strcpy(buffer+strlen(buffer), ", desc: ");
2325 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2329 MFREE(buffer, char, buffer_len);
2333 if ((c->methods[i].name == name) && ((desc == NULL) ||
2334 (c->methods[i].descriptor == desc)))
2337 #ifdef JOWENN_DEBUG2
2338 class_showconstantpool(c);
2339 log_text("class_findmethod: returning NULL");
2346 /************************* Function: class_findmethod **************************
2348 Searches a 'classinfo' structure for a method having the given name and
2350 If type is NULL, it is ignored.
2352 *******************************************************************************/
2354 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2358 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2360 int buffer_len, pos;
2362 #ifdef JOWENN_DEBUG1
2365 utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2367 buffer = MNEW(char, buffer_len);
2369 strcpy(buffer, "class_findmethod: method:");
2370 utf_sprint(buffer+strlen(buffer), name);
2371 strcpy(buffer+strlen(buffer), ", desc: ");
2372 utf_sprint(buffer+strlen(buffer), desc);
2373 strcpy(buffer+strlen(buffer), ", classname: ");
2374 utf_sprint(buffer+strlen(buffer), c->name);
2378 MFREE(buffer, char, buffer_len);
2380 for (i = 0; i < c->methodscount; i++) {
2381 #ifdef JOWENN_DEBUG2
2383 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2385 buffer = MNEW(char, buffer_len);
2387 strcpy(buffer, "class_findmethod: comparing to method:");
2388 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2389 strcpy(buffer+strlen(buffer), ", desc: ");
2390 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2394 MFREE(buffer, char, buffer_len);
2398 if ((c->methods[i].name == name) && ((desc == NULL) ||
2399 (c->methods[i].descriptor == desc)))
2400 return &(c->methods[i]);
2402 #ifdef JOWENN_DEBUG2
2403 class_showconstantpool(c);
2404 log_text("class_findmethod: returning NULL");
2408 s4 idx=class_findmethodIndex(c,name,desc);
2409 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2410 if (idx==-1) return NULL;
2411 return &(c->methods[idx]);
2419 /************************* Function: class_findmethod_approx ******************
2421 like class_findmethod but ignores the return value when comparing the
2424 *******************************************************************************/
2426 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2430 for (i = 0; i < c->methodscount; i++)
2431 if (c->methods[i].name == name) {
2432 utf *meth_descr = c->methods[i].descriptor;
2436 return &(c->methods[i]);
2438 if (desc->blength <= meth_descr->blength) {
2439 /* current position in utf text */
2440 char *desc_utf_ptr = desc->text;
2441 char *meth_utf_ptr = meth_descr->text;
2442 /* points behind utf strings */
2443 char *desc_end = utf_end(desc);
2444 char *meth_end = utf_end(meth_descr);
2447 /* compare argument types */
2448 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2450 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2451 break; /* no match */
2454 return &(c->methods[i]); /* all parameter types equal */
2462 /***************** Function: class_resolvemethod_approx ***********************
2464 Searches a class and every super class for a method (without paying
2465 attention to the return value)
2467 *******************************************************************************/
2469 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2472 /* search for method (ignore returntype) */
2473 methodinfo *m = class_findmethod_approx (c, name, desc);
2476 /* search superclass */
2483 /************************* Function: class_resolvemethod ***********************
2485 Searches a class and every super class for a method.
2487 *******************************************************************************/
2489 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2492 methodinfo *m = class_findmethod(c, name, desc);
2494 /* search superclass */
2502 /************************* Function: class_issubclass **************************
2504 Checks if sub is a descendant of super.
2506 *******************************************************************************/
2508 bool class_issubclass(classinfo *sub, classinfo *super)
2511 if (!sub) return false;
2512 if (sub==super) return true;
2519 /****************** Initialization function for classes ******************
2521 In Java, every class can have a static initialization function. This
2522 function has to be called BEFORE calling other methods or accessing static
2525 *******************************************************************************/
2528 extern int blockInts;
2531 void class_init(classinfo *c)
2534 java_objectheader *exceptionptr;
2539 if (!makeinitializations)
2543 c -> initialized = true;
2548 count_class_inits++;
2552 class_init (c->super);
2553 for (i=0; i < c->interfacescount; i++)
2554 class_init(c->interfaces[i]); /* real */
2556 m = class_findmethod (c, utf_clinit, utf_fidesc);
2559 sprintf (logtext, "Class ");
2560 utf_sprint (logtext+strlen(logtext), c->name);
2561 sprintf (logtext+strlen(logtext), " has no initializer");
2564 /* goto callinitialize;*/
2568 if (! (m->flags & ACC_STATIC))
2569 panic ("Class initializer is not static!");
2572 sprintf (logtext, "Starting initializer for class: ");
2573 utf_sprint (logtext+strlen(logtext), c->name);
2582 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2585 assert(blockInts == 0);
2590 printf ("#### Initializer of ");
2591 utf_display (c->name);
2592 printf (" has thrown: ");
2593 utf_display (exceptionptr->vftbl->class->name);
2599 sprintf (logtext, "Finished initializer for class: ");
2600 utf_sprint (logtext+strlen(logtext), c->name);
2603 if (c->name == utf_systemclass) {
2604 /* class java.lang.System requires explicit initialization */
2607 printf ("#### Initializing class System");
2609 /* find initializing method */
2610 m = class_findmethod (c,
2611 utf_initsystemclass,
2615 /* no method found */
2616 /* printf("initializeSystemClass failed"); */
2624 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2627 assert(blockInts == 0);
2632 printf ("#### initializeSystemClass has thrown: ");
2633 utf_display (exceptionptr->vftbl->class->name);
2644 /********* Function: find_class_method_constant *********/
2645 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2650 for (i=0; i<c->cpcount; i++) {
2652 e = c -> cpinfos [i];
2655 switch (c -> cptags [i]) {
2656 case CONSTANT_Methodref:
2658 constant_FMIref *fmi = e;
2659 if ( (fmi->class->name == c1)
2660 && (fmi->name == m1)
2661 && (fmi->descriptor == d1)) {
2668 case CONSTANT_InterfaceMethodref:
2670 constant_FMIref *fmi = e;
2671 if ( (fmi->class->name == c1)
2672 && (fmi->name == m1)
2673 && (fmi->descriptor == d1)) {
2687 void class_showconstanti(classinfo *c, int ii)
2693 printf ("#%d: ", (int) i);
2695 switch (c->cptags [i]) {
2696 case CONSTANT_Class:
2697 printf("Classreference -> ");
2698 utf_display(((classinfo*)e)->name);
2701 case CONSTANT_Fieldref:
2702 printf("Fieldref -> "); goto displayFMIi;
2703 case CONSTANT_Methodref:
2704 printf("Methodref -> "); goto displayFMIi;
2705 case CONSTANT_InterfaceMethodref:
2706 printf("InterfaceMethod -> "); goto displayFMIi;
2709 constant_FMIref *fmi = e;
2710 utf_display(fmi->class->name);
2712 utf_display(fmi->name);
2714 utf_display(fmi->descriptor);
2718 case CONSTANT_String:
2719 printf("String -> ");
2722 case CONSTANT_Integer:
2723 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2725 case CONSTANT_Float:
2726 printf("Float -> %f", ((constant_float*)e)->value);
2728 case CONSTANT_Double:
2729 printf("Double -> %f", ((constant_double*)e)->value);
2733 u8 v = ((constant_long*)e)->value;
2735 printf("Long -> %ld", (long int) v);
2737 printf("Long -> HI: %ld, LO: %ld\n",
2738 (long int) v.high, (long int) v.low);
2742 case CONSTANT_NameAndType:
2744 constant_nameandtype *cnt = e;
2745 printf("NameAndType: ");
2746 utf_display(cnt->name);
2748 utf_display(cnt->descriptor);
2756 panic("Invalid type of ConstantPool-Entry");
2763 void class_showconstantpool (classinfo *c)
2768 printf ("---- dump of constant pool ----\n");
2770 for (i=0; i<c->cpcount; i++) {
2771 printf ("#%d: ", (int) i);
2773 e = c -> cpinfos [i];
2776 switch (c -> cptags [i]) {
2777 case CONSTANT_Class:
2778 printf ("Classreference -> ");
2779 utf_display ( ((classinfo*)e) -> name );
2782 case CONSTANT_Fieldref:
2783 printf ("Fieldref -> "); goto displayFMI;
2784 case CONSTANT_Methodref:
2785 printf ("Methodref -> "); goto displayFMI;
2786 case CONSTANT_InterfaceMethodref:
2787 printf ("InterfaceMethod -> "); goto displayFMI;
2790 constant_FMIref *fmi = e;
2791 utf_display ( fmi->class->name );
2793 utf_display ( fmi->name);
2795 utf_display ( fmi->descriptor );
2799 case CONSTANT_String:
2800 printf ("String -> ");
2803 case CONSTANT_Integer:
2804 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2806 case CONSTANT_Float:
2807 printf ("Float -> %f", ((constant_float*)e) -> value);
2809 case CONSTANT_Double:
2810 printf ("Double -> %f", ((constant_double*)e) -> value);
2814 u8 v = ((constant_long*)e) -> value;
2816 printf ("Long -> %ld", (long int) v);
2818 printf ("Long -> HI: %ld, LO: %ld\n",
2819 (long int) v.high, (long int) v.low);
2823 case CONSTANT_NameAndType:
2825 constant_nameandtype *cnt = e;
2826 printf ("NameAndType: ");
2827 utf_display (cnt->name);
2829 utf_display (cnt->descriptor);
2833 printf ("Utf8 -> ");
2837 panic ("Invalid type of ConstantPool-Entry");
2847 /********** Function: class_showmethods (debugging only) *************/
2849 void class_showmethods (classinfo *c)
2853 printf ("--------- Fields and Methods ----------------\n");
2854 printf ("Flags: "); printflags (c->flags); printf ("\n");
2856 printf ("This: "); utf_display (c->name); printf ("\n");
2858 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2860 printf ("Index: %d\n", c->index);
2862 printf ("interfaces:\n");
2863 for (i=0; i < c-> interfacescount; i++) {
2865 utf_display (c -> interfaces[i] -> name);
2866 printf (" (%d)\n", c->interfaces[i] -> index);
2869 printf ("fields:\n");
2870 for (i=0; i < c -> fieldscount; i++) {
2871 field_display (&(c -> fields[i]));
2874 printf ("methods:\n");
2875 for (i=0; i < c -> methodscount; i++) {
2876 methodinfo *m = &(c->methods[i]);
2877 if ( !(m->flags & ACC_STATIC))
2878 printf ("vftblindex: %d ", m->vftblindex);
2880 method_display ( m );
2884 printf ("Virtual function table:\n");
2885 for (i=0; i<c->vftbl->vftbllength; i++) {
2886 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2893 /******************************************************************************/
2894 /******************* General functions for the class loader *******************/
2895 /******************************************************************************/
2897 /********************* Function: loader_load ***********************************
2899 Loads and links the class desired class and each class and interface
2901 Returns: a pointer to this class
2903 *******************************************************************************/
2905 static int loader_load_running = 0;
2907 classinfo *loader_load (utf *topname)
2911 long int starttime=0,stoptime=0;
2913 /* avoid recursive calls */
2914 if (loader_load_running)
2915 return class_new(topname);
2916 loader_load_running++;
2918 intsDisable(); /* schani */
2921 starttime = getcputime();
2923 top = class_new (topname);
2926 while ( (c = list_first(&unloadedclasses)) ) {
2927 if (!class_load (c)) {
2928 list_remove (&unloadedclasses, c);
2934 while ( (c = list_first(&unlinkedclasses)) ) {
2939 loader_compute_subclasses();
2942 if (getloadingtime) {
2943 stoptime = getcputime();
2944 loadingtime += (stoptime-starttime);
2947 intsRestore(); /* schani */
2949 loader_load_running--;
2955 /**************** function: create_primitive_classes ***************************
2957 create classes representing primitive types
2959 ********************************************************************************/
2962 void create_primitive_classes()
2966 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2967 /* create primitive class */
2968 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2969 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2970 c -> impldBy = NULL;
2972 /* prevent loader from loading primitive class */
2973 list_remove (&unloadedclasses, c);
2974 /* add to unlinked classes */
2975 list_addlast (&unlinkedclasses, c);
2976 c -> super = class_java_lang_Object;
2979 primitivetype_table[i].class_primitive = c;
2981 /* create class for wrapping the primitive type */
2982 primitivetype_table[i].class_wrap =
2983 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2984 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2985 primitivetype_table[i].class_wrap -> impldBy = NULL;
2987 /* create the primitive array class */
2988 if (primitivetype_table[i].arrayname) {
2989 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2990 primitivetype_table[i].arrayclass = c;
2991 if (!c->linked) class_link(c);
2992 primitivetype_table[i].arrayvftbl = c->vftbl;
2997 /**************** function: class_primitive_from_sig ***************************
2999 return the primitive class indicated by the given signature character
3001 If the descriptor does not indicate a valid primitive type the
3002 return value is NULL.
3004 ********************************************************************************/
3006 classinfo *class_primitive_from_sig(char sig)
3009 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3010 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3011 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3012 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3013 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3014 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3015 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3016 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3017 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3022 /****************** function: class_from_descriptor ****************************
3024 return the class indicated by the given descriptor
3026 utf_ptr....first character of descriptor
3027 end_ptr....first character after the end of the string
3028 next.......if non-NULL, *next is set to the first character after
3030 mode.......what to do if a class descriptor is parsed successfully:
3031 CLASSLOAD_SKIP...skip it and return something != NULL
3032 CLASSLOAD_NEW....get classinfo * via class_new
3033 CLASSLOAD_LOAD...get classinfo * via loader_load
3035 If the descriptor is invalid the return value is NULL
3037 ********************************************************************************/
3039 classinfo *class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
3041 char *start = utf_ptr;
3045 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3046 if (error) return NULL;
3047 if (next) *next = utf_ptr;
3055 if (mode == CLASSLOAD_SKIP) return class_java_lang_Object;
3056 name = utf_new(start,utf_ptr-start);
3057 return (mode == CLASSLOAD_LOAD) ? loader_load(name) : class_new(name);
3059 return class_primitive_from_sig(*start);
3063 /***************** function: create_array_class ********************************
3065 create class representing an array
3067 ********************************************************************************/
3071 classinfo *create_array_class(utf *u)
3073 classinfo *c = class_new (u);
3074 /* prevent loader from loading the array class */
3075 list_remove (&unloadedclasses, c);
3076 /* add to unlinked classes */
3077 list_addlast (&unlinkedclasses, c);
3078 c -> super = class_java_lang_Object;
3084 /*************** function: create_pseudo_classes *******************************
3086 create pseudo classes used by the typechecker
3088 ********************************************************************************/
3091 create_pseudo_classes()
3093 /* pseudo class for Arraystubs (extends java.lang.Object) */
3095 pseudo_class_Arraystub = class_new( utf_new_char(";Arraystub;") );
3096 list_remove(&unloadedclasses,pseudo_class_Arraystub);
3098 pseudo_class_Arraystub->super = class_java_lang_Object;
3099 pseudo_class_Arraystub->interfacescount = 2;
3100 pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
3101 pseudo_class_Arraystub->interfaces[0] =
3102 class_java_lang_Cloneable;
3103 pseudo_class_Arraystub->interfaces[1] =
3104 class_java_io_Serializable;
3106 list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
3107 class_link(pseudo_class_Arraystub);
3109 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3111 /* pseudo class representing the null type */
3113 pseudo_class_Null = class_new( utf_new_char(";Null;") );
3114 list_remove(&unloadedclasses,pseudo_class_Null);
3116 pseudo_class_Null->super = class_java_lang_Object;
3118 list_addlast(&unlinkedclasses,pseudo_class_Null);
3119 class_link(pseudo_class_Null);
3122 /********************** Function: loader_init **********************************
3124 Initializes all lists and loads all classes required for the system or the
3127 *******************************************************************************/
3129 void loader_init (u1 * stackbottom)
3134 log_text("Entering loader_init");
3137 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
3138 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
3139 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
3141 /* create utf-symbols for pointer comparison of frequently used strings */
3142 utf_innerclasses = utf_new_char("InnerClasses");
3143 utf_constantvalue = utf_new_char("ConstantValue");
3144 utf_code = utf_new_char("Code");
3145 utf_finalize = utf_new_char("finalize");
3146 utf_fidesc = utf_new_char("()V");
3147 utf_clinit = utf_new_char("<clinit>");
3148 utf_initsystemclass = utf_new_char("initializeSystemClass");
3149 utf_systemclass = utf_new_char("java/lang/System");
3150 utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
3151 utf_initialize =utf_new_char("initialize");
3152 utf_initializedesc =utf_new_char("(I)V");
3154 utf_vmclass =utf_new_char("java/lang/VMClass");
3156 /* create some important classes */
3157 /* These classes have to be created now because the classinfo
3158 * pointers are used in the loading code.
3160 class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
3161 class_java_lang_String = class_new( utf_new_char("java/lang/String") );
3162 class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
3163 class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
3165 log_text("loader_init: java/lang/Object");
3166 /* load the classes which were created above */
3167 loader_load (class_java_lang_Object->name);
3169 loader_inited=1; /*JOWENN*/
3171 class_java_lang_Throwable =
3172 loader_load( utf_new_char("java/lang/Throwable") );
3174 log_text("loader_init: loader_load: java/lang/ClassCastException");
3175 class_java_lang_ClassCastException =
3176 loader_load ( utf_new_char ("java/lang/ClassCastException") );
3177 class_java_lang_NullPointerException =
3178 loader_load ( utf_new_char ("java/lang/NullPointerException") );
3179 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
3180 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
3181 class_java_lang_NegativeArraySizeException = loader_load (
3182 utf_new_char ("java/lang/NegativeArraySizeException") );
3183 class_java_lang_OutOfMemoryError = loader_load (
3184 utf_new_char ("java/lang/OutOfMemoryError") );
3185 class_java_lang_ArrayStoreException =
3186 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
3187 class_java_lang_ArithmeticException =
3188 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
3189 class_java_lang_ThreadDeath = /* schani */
3190 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
3191 /* create classes representing primitive types */
3192 create_primitive_classes();
3194 /* create classes used by the typechecker */
3195 create_pseudo_classes();
3197 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3198 stringtable_update();
3206 log_text("loader_init: creating global proto_java_lang_ClassCastException");
3207 proto_java_lang_ClassCastException =
3208 builtin_new(class_java_lang_ClassCastException);
3209 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3211 log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3213 proto_java_lang_NullPointerException =
3214 builtin_new(class_java_lang_NullPointerException);
3215 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3216 log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3218 proto_java_lang_ArrayIndexOutOfBoundsException =
3219 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3220 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3222 proto_java_lang_NegativeArraySizeException =
3223 builtin_new(class_java_lang_NegativeArraySizeException);
3224 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3226 proto_java_lang_OutOfMemoryError =
3227 builtin_new(class_java_lang_OutOfMemoryError);
3228 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3230 proto_java_lang_ArithmeticException =
3231 builtin_new(class_java_lang_ArithmeticException);
3232 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3234 proto_java_lang_ArrayStoreException =
3235 builtin_new(class_java_lang_ArrayStoreException);
3236 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3238 proto_java_lang_ThreadDeath = /* schani */
3239 builtin_new(class_java_lang_ThreadDeath);
3240 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3249 /********************* Function: loader_initclasses ****************************
3251 Initializes all loaded but uninitialized classes
3253 *******************************************************************************/
3255 void loader_initclasses ()
3259 intsDisable(); /* schani */
3261 if (makeinitializations) {
3262 c = list_first (&linkedclasses);
3265 c = list_next (&linkedclasses, c);
3269 intsRestore(); /* schani */
3272 static s4 classvalue;
3274 static void loader_compute_class_values (classinfo *c)
3278 c->vftbl->baseval = ++classvalue;
3281 while (subs != NULL) {
3282 loader_compute_class_values(subs);
3283 subs = subs->nextsub;
3285 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3290 for (i = 0; i < c->index; i++)
3292 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3293 utf_display(c->name);
3301 void loader_compute_subclasses ()
3305 intsDisable(); /* schani */
3307 c = list_first (&linkedclasses);
3309 if (!(c->flags & ACC_INTERFACE)) {
3313 c = list_next (&linkedclasses, c);
3316 c = list_first (&linkedclasses);
3318 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3319 c->nextsub = c->super->sub;
3322 c = list_next (&linkedclasses, c);
3325 loader_compute_class_values(class_java_lang_Object);
3327 intsRestore(); /* schani */
3332 /******************** function classloader_buffer ******************************
3334 sets buffer for reading classdata
3336 *******************************************************************************/
3338 void classload_buffer(u1 *buf, int len)
3341 classbuffer_size = len;
3342 classbuf_pos = buf - 1;
3346 /******************** Function: loader_close ***********************************
3350 *******************************************************************************/
3352 void loader_close ()
3356 while ( (c=list_first(&unloadedclasses)) ) {
3357 list_remove (&unloadedclasses,c);
3360 while ( (c=list_first(&unlinkedclasses)) ) {
3361 list_remove (&unlinkedclasses,c);
3364 while ( (c=list_first(&linkedclasses)) ) {
3365 list_remove (&linkedclasses,c);
3372 * These are local overrides for various environment variables in Emacs.
3373 * Please do not remove this and leave it at the end of the file, where
3374 * Emacs will automagically detect them.
3375 * ---------------------------------------------------------------------
3378 * indent-tabs-mode: t