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 881 2004-01-13 19:57:08Z edwin $
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
64 /* global variables ***********************************************************/
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 static s4 interfaceindex; /* sequential numbering of interfaces */
78 list unloadedclasses; /* list of all referenced but not loaded classes */
79 list unlinkedclasses; /* list of all loaded but not linked classes */
80 list linkedclasses; /* list of all completely linked classes */
83 /* utf-symbols for pointer comparison of frequently used strings */
85 static utf *utf_innerclasses; /* InnerClasses */
86 static utf *utf_constantvalue; /* ConstantValue */
87 static utf *utf_code; /* Code */
88 static utf *utf_finalize; /* finalize */
89 static utf *utf_fidesc; /* ()V changed */
90 static utf *utf_init; /* <init> */
91 static utf *utf_clinit; /* <clinit> */
92 static utf *utf_initsystemclass; /* initializeSystemClass */
93 static utf *utf_systemclass; /* java/lang/System */
94 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
95 static utf *utf_vmclass; /* java/lang/VMClassLoader */
96 static utf *utf_initialize;
97 static utf *utf_initializedesc;
98 static utf *utf_java_lang_Object; /* java/lang/Object */
111 /* important system classes ***************************************************/
113 classinfo *class_java_lang_Object;
114 classinfo *class_java_lang_String;
116 classinfo *class_java_lang_Throwable;
117 classinfo *class_java_lang_Cloneable;
118 classinfo *class_java_io_Serializable;
120 /* Pseudo classes for the typechecker */
121 classinfo *pseudo_class_Arraystub = NULL;
122 classinfo *pseudo_class_Null = NULL;
123 classinfo *pseudo_class_New = 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 utf *array_packagename = NULL;
140 static int loader_inited = 0;
143 /********************************************************************
144 list of classpath entries (either filesystem directories or
146 ********************************************************************/
147 static classpath_info *classpath_entries=0;
150 /******************************************************************************
152 structure for primitive classes: contains the class for wrapping the
153 primitive type, the primitive class, the name of the class for wrapping,
154 the one character type signature and the name of the primitive class
156 ******************************************************************************/
158 /* CAUTION: Don't change the order of the types. This table is indexed
159 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
161 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
162 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
163 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
164 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
165 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
166 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
167 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
168 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
169 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
170 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
174 /* instances of important system classes **************************************/
176 java_objectheader *proto_java_lang_ClassCastException;
177 java_objectheader *proto_java_lang_NullPointerException;
178 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
179 java_objectheader *proto_java_lang_NegativeArraySizeException;
180 java_objectheader *proto_java_lang_OutOfMemoryError;
181 java_objectheader *proto_java_lang_ArithmeticException;
182 java_objectheader *proto_java_lang_ArrayStoreException;
183 java_objectheader *proto_java_lang_ThreadDeath;
185 /************* functions for reading classdata *********************************
187 getting classdata in blocks of variable size
188 (8,16,32,64-bit integer or float)
190 *******************************************************************************/
192 static char *classpath = ""; /* searchpath for classfiles */
193 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
194 static u1 *classbuf_pos; /* current position in classfile buffer */
195 static int classbuffer_size; /* size of classfile-data */
197 /* assert that at least <len> bytes are left to read */
198 /* <len> is limited to the range of non-negative s4 values */
199 #define ASSERT_LEFT(len) \
200 do {if ( ((s4)(len)) < 0 \
201 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
202 panic("Unexpected end of classfile"); } while(0)
204 /* transfer block of classfile data into a buffer */
206 #define suck_nbytes(buffer,len) \
207 do {ASSERT_LEFT(len); \
208 memcpy(buffer,classbuf_pos+1,len); \
209 classbuf_pos+=len;} while (0)
211 /* skip block of classfile data */
213 #define skip_nbytes(len) \
214 do {ASSERT_LEFT(len); \
215 classbuf_pos+=len;} while(0)
220 return *++classbuf_pos;
224 u1 a=suck_u1(), b=suck_u1();
225 return ((u2)a<<8)+(u2)b;
229 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
230 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
232 #define suck_s8() (s8) suck_u8()
233 #define suck_s2() (s2) suck_u2()
234 #define suck_s4() (s4) suck_u4()
235 #define suck_s1() (s1) suck_u1()
238 /* get u8 from classfile data */
245 return (hi << 32) + lo;
255 /* get float from classfile data */
256 static float suck_float()
263 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
264 memcpy((u1*) (&f), buffer, 4);
266 suck_nbytes((u1*) (&f), 4);
269 PANICIF (sizeof(float) != 4, "Incompatible float-format");
275 /* get double from classfile data */
276 static double suck_double()
283 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
284 memcpy((u1*) (&d), buffer, 8);
286 suck_nbytes((u1*) (&d), 8);
289 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
295 /************************** function suck_init *********************************
297 called once at startup, sets the searchpath for the classfiles
299 *******************************************************************************/
301 void suck_init(char *cpath)
308 union classpath_info *tmp;
309 union classpath_info *insertAfter=0;
314 if (classpath_entries) panic("suck_init should be called only once");
315 for(start=classpath;(*start)!='\0';) {
316 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
319 filenamelen=(end-start);
353 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
354 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
355 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
358 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
359 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
360 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
365 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
367 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
368 strncpy(filename,start,filenamelen);
369 filename[filenamelen+1]='\0';
374 unzFile uf=unzOpen(filename);
376 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
377 tmp->archive.type=CLASSPATH_ARCHIVE;
383 panic("Zip/JAR not supported");
387 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
388 tmp->filepath.type=CLASSPATH_PATH;
389 tmp->filepath.next=0;
390 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
391 filename[filenamelen]='/';
392 filename[filenamelen+1]='\0';
396 tmp->filepath.filename=filename;
397 tmp->filepath.pathlen=filenamelen;
403 insertAfter->filepath.next=tmp;
405 classpath_entries=tmp;
410 if ((*end)==':') start=end+1; else start=end;
413 if (filename!=0) free(filename);
418 /************************** function suck_start ********************************
420 returns true if classbuffer is already loaded or a file for the
421 specified class has succussfully been read in. All directories of
422 the searchpath are used to find the classfile (<classname>.class).
423 Returns false if no classfile is found and writes an error message.
425 *******************************************************************************/
427 bool suck_start(utf *classname)
429 classpath_info *currPos;
432 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
438 if (classbuffer) return true; /* classbuffer is already valid */
440 utf_ptr = classname->text;
441 while (utf_ptr < utf_end(classname)) {
442 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
444 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
446 filename[filenamelen++] = c;
448 strcpy(filename + filenamelen, ".class");
450 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
452 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
453 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
454 unz_file_info file_info;
455 /*log_text("Class found in zip file");*/
456 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
457 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
458 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
459 classbuffer_size = file_info.uncompressed_size;
460 classbuffer = MNEW(u1, classbuffer_size);
461 classbuf_pos = classbuffer - 1;
462 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
463 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
464 unzCloseCurrentFile(currPos->archive.uf);
467 MFREE(classbuffer, u1, classbuffer_size);
468 log_text("Error while unzipping");
470 } else log_text("Error while opening file in archive");
471 } else log_text("Error while retrieving fileinfo");
473 unzCloseCurrentFile(currPos->archive.uf);
477 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
478 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
479 classfile = fopen(currPos->filepath.filename, "r");
480 if (classfile) { /* file exists */
482 /* determine size of classfile */
484 /* dolog("File: %s",filename); */
486 err = stat(currPos->filepath.filename, &buffer);
488 if (!err) { /* read classfile data */
489 classbuffer_size = buffer.st_size;
490 classbuffer = MNEW(u1, classbuffer_size);
491 classbuf_pos = classbuffer - 1;
492 fread(classbuffer, 1, classbuffer_size, classfile);
503 dolog("Warning: Can not open class file '%s'", filename);
510 /************************** function suck_stop *********************************
512 frees memory for buffer with classfile data.
513 Caution: this function may only be called if buffer has been allocated
514 by suck_start with reading a file
516 *******************************************************************************/
520 /* determine amount of classdata not retrieved by suck-operations */
522 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
524 if (classdata_left > 0) {
526 dolog("There are %d extra bytes at end of classfile",
528 /* The JVM spec disallows extra bytes. */
529 panic("Extra bytes at end of classfile");
534 MFREE(classbuffer, u1, classbuffer_size);
539 /******************************************************************************/
540 /******************* Some support functions ***********************************/
541 /******************************************************************************/
543 void fprintflags (FILE *fp, u2 f)
545 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
546 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
547 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
548 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
549 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
550 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
551 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
552 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
553 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
554 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
555 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
559 /********** internal function: printflags (only for debugging) ***************/
561 void printflags(u2 f)
563 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
564 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
565 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
566 if ( f & ACC_STATIC ) printf (" STATIC");
567 if ( f & ACC_FINAL ) printf (" FINAL");
568 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
569 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
570 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
571 if ( f & ACC_NATIVE ) printf (" NATIVE");
572 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
573 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
577 /************************* Function: skipattribute *****************************
579 skips a (1) 'attribute' structure in the class file
581 *******************************************************************************/
583 static void skipattribute()
592 /********************** Function: skipattributebody ****************************
594 skips an attribute after the 16 bit reference to attribute_name has already
597 *******************************************************************************/
599 static void skipattributebody()
607 /************************* Function: skipattributes ****************************
609 skips num attribute structures
611 *******************************************************************************/
613 static void skipattributes(u4 num)
616 for (i = 0; i < num; i++)
621 /******************** function: innerclass_getconstant ************************
623 like class_getconstant, but if cptags is ZERO null is returned
625 *******************************************************************************/
627 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
629 /* invalid position in constantpool */
630 if (pos >= c->cpcount)
631 panic("Attempt to access constant outside range");
633 /* constantpool entry of type 0 */
637 /* check type of constantpool entry */
638 if (c->cptags[pos] != ctype) {
639 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
640 (int) ctype, (int) c->cptags[pos] );
643 return c->cpinfos[pos];
647 /************************ function: attribute_load ****************************
649 read attributes from classfile
651 *******************************************************************************/
653 static void attribute_load(u4 num, classinfo *c)
657 for (i = 0; i < num; i++) {
658 /* retrieve attribute name */
659 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
661 if (aname == utf_innerclasses) {
662 /* innerclasses attribute */
664 if (c->innerclass != NULL)
665 panic("Class has more than one InnerClasses attribute");
667 /* skip attribute length */
669 /* number of records */
670 c->innerclasscount = suck_u2();
671 /* allocate memory for innerclass structure */
672 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
674 for (j = 0; j < c->innerclasscount; j++) {
675 /* The innerclass structure contains a class with an encoded name,
676 its defining scope, its simple name and a bitmask of the access flags.
677 If an inner class is not a member, its outer_class is NULL,
678 if a class is anonymous, its name is NULL. */
680 innerclassinfo *info = c->innerclass + j;
682 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
683 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
684 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
685 info->flags = suck_u2(); /* access_flags bitmask */
689 /* unknown attribute */
696 /******************* function: checkfielddescriptor ****************************
698 checks whether a field-descriptor is valid and aborts otherwise
699 all referenced classes are inserted into the list of unloaded classes
701 *******************************************************************************/
703 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
705 class_from_descriptor(utf_ptr,end_pos,NULL,
707 | CLASSLOAD_NULLPRIMITIVE
709 | CLASSLOAD_CHECKEND);
711 /* XXX use the following if -noverify */
713 char *tstart; /* pointer to start of classname */
715 char *start = utf_ptr;
717 switch (*utf_ptr++) {
731 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
732 panic ("Ill formed descriptor");
736 panic ("Ill formed descriptor");
739 /* exceeding characters */
740 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
745 /******************* function checkmethoddescriptor ****************************
747 checks whether a method-descriptor is valid and aborts otherwise.
748 All referenced classes are inserted into the list of unloaded classes.
750 The number of arguments is returned. A long or double argument is counted
753 *******************************************************************************/
755 static int checkmethoddescriptor (utf *d)
757 char *utf_ptr = d->text; /* current position in utf text */
758 char *end_pos = utf_end(d); /* points behind utf string */
759 int argcount = 0; /* number of arguments */
761 /* method descriptor must start with parenthesis */
762 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
764 /* check arguments */
765 while (utf_ptr != end_pos && *utf_ptr != ')') {
766 /* XXX we cannot count the this argument here because
767 * we don't know if the method is static. */
768 if (*utf_ptr == 'J' || *utf_ptr == 'D')
772 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
774 | CLASSLOAD_NULLPRIMITIVE
778 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
779 utf_ptr++; /* skip ')' */
781 class_from_descriptor(utf_ptr,end_pos,NULL,
783 | CLASSLOAD_NULLPRIMITIVE
784 | CLASSLOAD_CHECKEND);
787 panic("Invalid method descriptor: too many arguments");
791 /* XXX use the following if -noverify */
793 /* XXX check length */
794 /* check arguments */
795 while ((c = *utf_ptr++) != ')') {
812 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
813 panic ("Ill formed method descriptor");
817 panic ("Ill formed methodtype-descriptor");
821 /* check returntype */
823 /* returntype void */
824 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
827 /* treat as field-descriptor */
828 checkfielddescriptor (utf_ptr,end_pos);
833 /***************** Function: print_arraydescriptor ****************************
835 Debugging helper for displaying an arraydescriptor
837 *******************************************************************************/
839 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
842 fprintf(file, "<NULL>");
847 if (desc->componentvftbl) {
848 if (desc->componentvftbl->class)
849 utf_fprint(file, desc->componentvftbl->class->name);
851 fprintf(file, "<no classinfo>");
857 if (desc->elementvftbl) {
858 if (desc->elementvftbl->class)
859 utf_fprint(file, desc->elementvftbl->class->name);
861 fprintf(file, "<no classinfo>");
865 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
866 desc->dataoffset, desc->componentsize);
870 /******************************************************************************/
871 /************************** Functions for fields ****************************/
872 /******************************************************************************/
875 /************************ Function: field_load *********************************
877 Load everything about a class field from the class file and fill a
878 'fieldinfo' structure. For static fields, space in the data segment is
881 *******************************************************************************/
883 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
885 static void field_load(fieldinfo *f, classinfo *c)
889 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
891 f->flags = suck_u2(); /* ACC flags */
892 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
893 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
897 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
898 panic("Field with invalid name");
900 /* check flag consistency */
901 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
902 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
903 panic("Field has invalid access flags");
904 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
905 panic("Field is declared final and volatile");
906 if ((c->flags & ACC_INTERFACE) != 0) {
907 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
908 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
909 panic("Interface field is not declared static final public");
910 if ((f->flags & ACC_TRANSIENT) != 0)
911 panic("Interface field declared transient");
914 /* check descriptor */
915 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
918 f->type = jtype = desc_to_type(f->descriptor); /* data type */
919 f->offset = 0; /* offset from start of object */
924 case TYPE_INT: f->value.i = 0; break;
925 case TYPE_FLOAT: f->value.f = 0.0; break;
926 case TYPE_DOUBLE: f->value.d = 0.0; break;
927 case TYPE_ADDRESS: f->value.a = NULL; break;
930 f->value.l = 0; break;
932 f->value.l.low = 0; f->value.l.high = 0; break;
936 /* read attributes */
938 for (i = 0; i < attrnum; i++) {
941 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
943 if (aname != utf_constantvalue) {
944 /* unknown attribute */
948 /* constant value attribute */
950 if (pindex != field_load_NOVALUE)
951 panic("Field has more than one ConstantValue attribute");
953 /* check attribute length */
955 panic("ConstantValue attribute has invalid length");
957 /* index of value in constantpool */
960 /* initialize field with value from constantpool */
963 constant_integer *ci =
964 class_getconstant(c, pindex, CONSTANT_Integer);
965 f->value.i = ci->value;
971 class_getconstant(c, pindex, CONSTANT_Long);
972 f->value.l = cl->value;
978 class_getconstant(c, pindex, CONSTANT_Float);
979 f->value.f = cf->value;
984 constant_double *cd =
985 class_getconstant(c, pindex, CONSTANT_Double);
986 f->value.d = cd->value;
991 utf *u = class_getconstant(c, pindex, CONSTANT_String);
992 /* create javastring from compressed utf8-string */
993 f->value.a = literalstring_new(u);
998 log_text ("Invalid Constant - Type");
1005 /********************** function: field_free **********************************/
1007 static void field_free (fieldinfo *f)
1013 /**************** Function: field_display (debugging only) ********************/
1015 void field_display(fieldinfo *f)
1018 printflags(f->flags);
1020 utf_display(f->name);
1022 utf_display(f->descriptor);
1023 printf(" offset: %ld\n", (long int) (f->offset));
1027 /******************************************************************************/
1028 /************************* Functions for methods ******************************/
1029 /******************************************************************************/
1032 /*********************** Function: method_load *********************************
1034 Loads a method from the class file and fills an existing 'methodinfo'
1035 structure. For native methods, the function pointer field is set to the
1036 real function pointer, for JavaVM methods a pointer to the compiler is used
1039 *******************************************************************************/
1041 static void method_load(methodinfo *m, classinfo *c)
1047 count_all_methods++;
1052 m->flags = suck_u2();
1053 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1056 if (!is_valid_name_utf(m->name))
1057 panic("Method with invalid name");
1058 if (m->name->text[0] == '<'
1059 && m->name != utf_init && m->name != utf_clinit)
1060 panic("Method with invalid special name");
1063 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1064 argcount = checkmethoddescriptor(m->descriptor);
1065 if ((m->flags & ACC_STATIC) == 0)
1066 argcount++; /* count the 'this' argument */
1070 panic("Method has more than 255 arguments");
1072 /* check flag consistency */
1073 /* XXX could check if <clinit> is STATIC */
1074 if (m->name != utf_clinit) {
1075 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1076 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1077 panic("Method has invalid access flags");
1078 if ((m->flags & ACC_ABSTRACT) != 0) {
1079 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1080 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1081 panic("Abstract method has invalid flags set");
1083 if ((c->flags & ACC_INTERFACE) != 0) {
1084 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1085 != (ACC_ABSTRACT | ACC_PUBLIC))
1086 panic("Interface method is not declared abstract and public");
1088 if (m->name == utf_init) {
1089 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1090 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1091 panic("Instance initialization method has invalid flags set");
1097 m->exceptiontable = NULL;
1098 m->entrypoint = NULL;
1100 m->stubroutine = NULL;
1101 m->methodUsed = NOTUSED;
1104 m->subRedefsUsed = 0;
1108 if (!(m->flags & ACC_NATIVE)) {
1109 m->stubroutine = createcompilerstub(m);
1112 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1113 (m->flags & ACC_STATIC) != 0);
1115 m->stubroutine = createnativestub(f, m);
1120 attrnum = suck_u2();
1121 for (i = 0; i < attrnum; i++) {
1124 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1126 if (aname != utf_code) {
1127 skipattributebody();
1131 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1132 panic("Code attribute for native or abstract method");
1135 panic("Method has more than one Code attribute");
1138 m->maxstack = suck_u2();
1139 m->maxlocals = suck_u2();
1140 if (m->maxlocals < argcount)
1141 panic("max_locals is smaller than the number of arguments");
1143 codelen = suck_u4();
1145 panic("bytecode has zero length");
1146 if (codelen > 65536)
1147 panic("bytecode too long");
1148 m->jcodelength = codelen;
1149 m->jcode = MNEW(u1, m->jcodelength);
1150 suck_nbytes(m->jcode, m->jcodelength);
1151 m->exceptiontablelength = suck_u2();
1153 MNEW(exceptiontable, m->exceptiontablelength);
1156 count_vmcode_len += m->jcodelength + 18;
1157 count_extable_len += 8 * m->exceptiontablelength;
1160 for (e = 0; e < m->exceptiontablelength; e++) {
1162 m->exceptiontable[e].startpc = suck_u2();
1163 m->exceptiontable[e].endpc = suck_u2();
1164 m->exceptiontable[e].handlerpc = suck_u2();
1168 m->exceptiontable[e].catchtype = NULL;
1171 m->exceptiontable[e].catchtype =
1172 class_getconstant(c, idx, CONSTANT_Class);
1176 skipattributes(suck_u2());
1180 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1181 panic("Method missing Code attribute");
1185 /********************* Function: method_free ***********************************
1187 frees all memory that was allocated for this method
1189 *******************************************************************************/
1191 static void method_free(methodinfo *m)
1194 MFREE(m->jcode, u1, m->jcodelength);
1196 if (m->exceptiontable)
1197 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1200 CFREE(m->mcode, m->mcodelength);
1202 if (m->stubroutine) {
1203 if (m->flags & ACC_NATIVE) {
1204 removenativestub(m->stubroutine);
1207 removecompilerstub(m->stubroutine);
1213 /************** Function: method_display (debugging only) **************/
1215 void method_display(methodinfo *m)
1218 printflags(m->flags);
1220 utf_display(m->name);
1222 utf_display(m->descriptor);
1227 /******************** Function: method_canoverwrite ****************************
1229 Check if m and old are identical with respect to type and name. This means
1230 that old can be overwritten with m.
1232 *******************************************************************************/
1234 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1236 if (m->name != old->name) return false;
1237 if (m->descriptor != old->descriptor) return false;
1238 if (m->flags & ACC_STATIC) return false;
1245 /******************************************************************************/
1246 /************************ Functions for class *********************************/
1247 /******************************************************************************/
1250 /******************** function:: class_getconstant ******************************
1252 retrieves the value at position 'pos' of the constantpool of a class
1253 if the type of the value is other than 'ctype' the system is stopped
1255 *******************************************************************************/
1257 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1259 /* invalid position in constantpool */
1260 /* (pos == 0 is caught by type comparison) */
1261 if (pos >= c->cpcount)
1262 panic("Attempt to access constant outside range");
1264 /* check type of constantpool entry */
1266 if (c->cptags[pos] != ctype) {
1267 class_showconstantpool(c);
1268 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1269 (int) ctype, (int) c->cptags[pos]);
1272 return c->cpinfos[pos];
1276 /********************* Function: class_constanttype ****************************
1278 Determines the type of a class entry in the ConstantPool
1280 *******************************************************************************/
1282 u4 class_constanttype(classinfo *c, u4 pos)
1284 if (pos >= c->cpcount)
1285 panic("Attempt to access constant outside range");
1287 return c->cptags[pos];
1291 /******************** function: class_loadcpool ********************************
1293 loads the constantpool of a class,
1294 the entries are transformed into a simpler format
1295 by resolving references
1296 (a detailed overview of the compact structures can be found in global.h)
1298 *******************************************************************************/
1300 static void class_loadcpool(classinfo *c)
1303 /* The following structures are used to save information which cannot be
1304 processed during the first pass. After the complete constantpool has
1305 been traversed the references can be resolved.
1306 (only in specific order) */
1308 /* CONSTANT_Class_info entries */
1309 typedef struct forward_class {
1310 struct forward_class *next;
1315 /* CONSTANT_String */
1316 typedef struct forward_string {
1317 struct forward_string *next;
1322 /* CONSTANT_NameAndType */
1323 typedef struct forward_nameandtype {
1324 struct forward_nameandtype *next;
1328 } forward_nameandtype;
1330 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1331 typedef struct forward_fieldmethint {
1332 struct forward_fieldmethint *next;
1336 u2 nameandtype_index;
1337 } forward_fieldmethint;
1341 long int dumpsize = dump_size ();
1343 forward_class *forward_classes = NULL;
1344 forward_string *forward_strings = NULL;
1345 forward_nameandtype *forward_nameandtypes = NULL;
1346 forward_fieldmethint *forward_fieldmethints = NULL;
1348 /* number of entries in the constant_pool table plus one */
1349 u4 cpcount = c -> cpcount = suck_u2();
1350 /* allocate memory */
1351 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1352 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1355 panic("Invalid constant_pool_count (0)");
1358 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1361 /* initialize constantpool */
1362 for (idx=0; idx<cpcount; idx++) {
1363 cptags[idx] = CONSTANT_UNUSED;
1364 cpinfos[idx] = NULL;
1368 /******* first pass *******/
1369 /* entries which cannot be resolved now are written into
1370 temporary structures and traversed again later */
1373 while (idx < cpcount) {
1374 /* get constant type */
1378 case CONSTANT_Class: {
1379 forward_class *nfc = DNEW(forward_class);
1381 nfc -> next = forward_classes;
1382 forward_classes = nfc;
1384 nfc -> thisindex = idx;
1385 /* reference to CONSTANT_NameAndType */
1386 nfc -> name_index = suck_u2 ();
1392 case CONSTANT_Fieldref:
1393 case CONSTANT_Methodref:
1394 case CONSTANT_InterfaceMethodref: {
1395 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1397 nff -> next = forward_fieldmethints;
1398 forward_fieldmethints = nff;
1400 nff -> thisindex = idx;
1403 /* class or interface type that contains the declaration of the field or method */
1404 nff -> class_index = suck_u2 ();
1405 /* name and descriptor of the field or method */
1406 nff -> nameandtype_index = suck_u2 ();
1412 case CONSTANT_String: {
1413 forward_string *nfs = DNEW (forward_string);
1415 nfs -> next = forward_strings;
1416 forward_strings = nfs;
1418 nfs -> thisindex = idx;
1419 /* reference to CONSTANT_Utf8_info with string characters */
1420 nfs -> string_index = suck_u2 ();
1426 case CONSTANT_NameAndType: {
1427 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1429 nfn -> next = forward_nameandtypes;
1430 forward_nameandtypes = nfn;
1432 nfn -> thisindex = idx;
1433 /* reference to CONSTANT_Utf8_info containing simple name */
1434 nfn -> name_index = suck_u2 ();
1435 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1436 nfn -> sig_index = suck_u2 ();
1442 case CONSTANT_Integer: {
1443 constant_integer *ci = NEW (constant_integer);
1446 count_const_pool_len += sizeof(constant_integer);
1449 ci -> value = suck_s4 ();
1450 cptags [idx] = CONSTANT_Integer;
1457 case CONSTANT_Float: {
1458 constant_float *cf = NEW (constant_float);
1461 count_const_pool_len += sizeof(constant_float);
1464 cf -> value = suck_float ();
1465 cptags [idx] = CONSTANT_Float;
1471 case CONSTANT_Long: {
1472 constant_long *cl = NEW(constant_long);
1475 count_const_pool_len += sizeof(constant_long);
1478 cl -> value = suck_s8 ();
1479 cptags [idx] = CONSTANT_Long;
1483 panic("Long constant exceeds constant pool");
1487 case CONSTANT_Double: {
1488 constant_double *cd = NEW(constant_double);
1491 count_const_pool_len += sizeof(constant_double);
1494 cd -> value = suck_double ();
1495 cptags [idx] = CONSTANT_Double;
1499 panic("Double constant exceeds constant pool");
1503 case CONSTANT_Utf8: {
1505 /* number of bytes in the bytes array (not string-length) */
1506 u4 length = suck_u2();
1507 cptags [idx] = CONSTANT_Utf8;
1508 /* validate the string */
1509 ASSERT_LEFT(length);
1511 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1513 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1514 panic("Invalid UTF-8 string");
1516 /* insert utf-string into the utf-symboltable */
1517 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1518 /* skip bytes of the string */
1519 skip_nbytes(length);
1525 error ("Unkown constant type: %d",(int) t);
1533 /* resolve entries in temporary structures */
1535 while (forward_classes) {
1537 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1539 if (opt_verify && !is_valid_name_utf(name))
1540 panic("Class reference with invalid name");
1542 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1543 /* retrieve class from class-table */
1544 cpinfos [forward_classes -> thisindex] = class_new (name);
1546 forward_classes = forward_classes -> next;
1550 while (forward_strings) {
1552 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1554 log_text("forward_string:");
1555 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1557 log_text("\n------------------"); */
1558 /* resolve utf-string */
1559 cptags [forward_strings -> thisindex] = CONSTANT_String;
1560 cpinfos [forward_strings -> thisindex] = text;
1562 forward_strings = forward_strings -> next;
1565 while (forward_nameandtypes) {
1566 constant_nameandtype *cn = NEW (constant_nameandtype);
1569 count_const_pool_len += sizeof(constant_nameandtype);
1572 /* resolve simple name and descriptor */
1573 cn -> name = class_getconstant
1574 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1575 cn -> descriptor = class_getconstant
1576 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1580 if (!is_valid_name_utf(cn->name))
1581 panic("NameAndType with invalid name");
1582 /* disallow referencing <clinit> among others */
1583 if (cn->name->text[0] == '<' && cn->name != utf_init)
1584 panic("NameAndType with invalid special name");
1587 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1588 cpinfos [forward_nameandtypes -> thisindex] = cn;
1590 forward_nameandtypes = forward_nameandtypes -> next;
1594 while (forward_fieldmethints) {
1595 constant_nameandtype *nat;
1596 constant_FMIref *fmi = NEW (constant_FMIref);
1599 count_const_pool_len += sizeof(constant_FMIref);
1601 /* resolve simple name and descriptor */
1602 nat = class_getconstant
1603 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1606 log_text("trying to resolve:");
1607 log_text(nat->name->text);
1608 switch(forward_fieldmethints ->tag) {
1609 case CONSTANT_Fieldref:
1610 log_text("CONSTANT_Fieldref");
1612 case CONSTANT_InterfaceMethodref:
1613 log_text("CONSTANT_InterfaceMethodref");
1615 case CONSTANT_Methodref:
1616 log_text("CONSTANT_Methodref");
1620 fmi -> class = class_getconstant
1621 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1622 fmi -> name = nat -> name;
1623 fmi -> descriptor = nat -> descriptor;
1625 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1626 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1628 switch (forward_fieldmethints -> tag) {
1629 case CONSTANT_Fieldref: /* check validity of descriptor */
1630 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1632 case CONSTANT_InterfaceMethodref:
1633 case CONSTANT_Methodref: /* check validity of descriptor */
1634 checkmethoddescriptor (fmi->descriptor);
1638 forward_fieldmethints = forward_fieldmethints -> next;
1642 /* class_showconstantpool(c); */
1644 dump_release (dumpsize);
1648 /********************** Function: class_load ***********************************
1650 Loads everything interesting about a class from the class file. The
1651 'classinfo' structure must have been allocated previously.
1653 The super class and the interfaces implemented by this class need not be
1654 loaded. The link is set later by the function 'class_link'.
1656 The loaded class is removed from the list 'unloadedclasses' and added to
1657 the list 'unlinkedclasses'.
1659 *******************************************************************************/
1661 static int class_load(classinfo *c)
1667 count_class_loads++;
1670 /* output for debugging purposes */
1672 char logtext[MAXLOGTEXT];
1673 sprintf(logtext, "Loading class: ");
1674 utf_sprint(logtext + strlen(logtext), c->name);
1678 /* load classdata, throw exception on error */
1680 if (!suck_start(c->name)) {
1681 throw_noclassdeffounderror_message(c->name);
1685 /* check signature */
1686 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1690 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1691 error("File version %d.%d is not supported", (int) ma, (int) mi);
1696 c->erroneous_state = 0;
1697 c->initializing_thread = 0;
1699 c->classUsed = NOTUSED; /* not used initially CO-RT */
1703 c->flags = suck_u2();
1704 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1706 /* check ACC flags consistency */
1707 if ((c->flags & ACC_INTERFACE) != 0) {
1708 if ((c->flags & ACC_ABSTRACT) == 0) {
1709 /* XXX We work around this because interfaces in JDK 1.1 are
1710 * not declared abstract. */
1712 c->flags |= ACC_ABSTRACT;
1713 /* panic("Interface class not declared abstract"); */
1715 if ((c->flags & (ACC_FINAL | ACC_SUPER)) != 0)
1716 panic("Interface class has invalid flags");
1718 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1719 panic("Class is declared both abstract and final");
1723 if (class_getconstant(c, i, CONSTANT_Class) != c)
1724 panic("Invalid this_class in class file");
1726 /* retrieve superclass */
1727 if ((i = suck_u2())) {
1728 c->super = class_getconstant(c, i, CONSTANT_Class);
1730 /* java.lang.Object may not have a super class. */
1731 if (c->name == utf_java_lang_Object)
1732 panic("java.lang.Object with super class");
1734 /* Interfaces must have j.l.O as super class. */
1735 if ((c->flags & ACC_INTERFACE) != 0
1736 && c->super->name != utf_java_lang_Object)
1738 panic("Interface with super class other than java.lang.Object");
1743 /* This is only allowed for java.lang.Object. */
1744 if (c->name != utf_java_lang_Object)
1745 panic("Class (not java.lang.Object) without super class");
1748 /* retrieve interfaces */
1749 c->interfacescount = suck_u2();
1750 c->interfaces = MNEW(classinfo*, c->interfacescount);
1751 for (i = 0; i < c->interfacescount; i++) {
1753 class_getconstant(c, suck_u2(), CONSTANT_Class);
1757 c->fieldscount = suck_u2();
1758 /* utf_display(c->name);
1759 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1761 c->fields = GCNEW(fieldinfo, c->fieldscount);
1762 for (i = 0; i < c->fieldscount; i++) {
1763 field_load(&(c->fields[i]), c);
1767 c->methodscount = suck_u2();
1768 c->methods = MNEW(methodinfo, c->methodscount);
1769 for (i = 0; i < c->methodscount; i++) {
1770 method_load(&(c->methods[i]), c);
1773 /* Check if all fields and methods can be uniquely
1774 * identified by (name,descriptor). */
1776 /* We use a hash table here to avoid making the
1777 * average case quadratic in # of methods, fields.
1779 static int shift = 0;
1781 u2 *next; /* for chaining colliding hash entries */
1787 /* Allocate hashtable */
1788 len = c->methodscount;
1789 if (len < c->fieldscount) len = c->fieldscount;
1791 hashtab = MNEW(u2,(hashlen + len));
1792 next = hashtab + hashlen;
1794 /* Determine bitshift (to get good hash values) */
1804 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1805 for (i = 0; i<c->fieldscount; ++i) {
1806 fieldinfo *fi = c->fields + i;
1807 /* It's ok if we lose bits here */
1808 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1810 if ((old = hashtab[index]) != 0) {
1812 /* dolog("HASHHIT %d --> %d",index,old); */
1815 /* dolog("HASHCHECK %d",old); */
1816 if (c->fields[old].name == fi->name
1817 && c->fields[old].descriptor == fi->descriptor)
1819 dolog("Duplicate field (%d,%d):",i,old);
1820 log_utf(fi->name); log_utf(fi->descriptor);
1821 panic("Fields with same name and descriptor");
1823 } while ((old = next[old]) != 0);
1825 /* else dolog("HASHLUCKY"); */
1826 hashtab[index] = i+1;
1830 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1831 for (i = 0; i<c->methodscount; ++i) {
1832 methodinfo *mi = c->methods + i;
1833 /* It's ok if we lose bits here */
1834 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1836 if ((old = hashtab[index]) != 0) {
1838 /* dolog("HASHHIT %d --> %d",index,old); */
1841 /* dolog("HASHCHECK %d",old); */
1842 if (c->methods[old].name == mi->name
1843 && c->methods[old].descriptor == mi->descriptor)
1845 dolog("Duplicate method (%d,%d):",i,old);
1846 log_utf(mi->name); log_utf(mi->descriptor);
1847 panic("Methods with same name and descriptor");
1849 } while ((old = next[old]) != 0);
1851 /* else dolog("HASHLUCKY"); */
1852 hashtab[index] = i+1;
1855 MFREE(hashtab,u2,(hashlen + len));
1859 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1860 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1861 count_class_infos += sizeof(methodinfo) * c->methodscount;
1864 /* load variable-length attribute structures */
1865 attribute_load(suck_u2(), c);
1870 /* remove class from list of unloaded classes and
1871 add to list of unlinked classes */
1872 list_remove(&unloadedclasses, c);
1873 list_addlast(&unlinkedclasses, c);
1882 /************** internal Function: class_highestinterface ***********************
1884 Used by the function class_link to determine the amount of memory needed
1885 for the interface table.
1887 *******************************************************************************/
1889 static s4 class_highestinterface(classinfo *c)
1894 if (!(c->flags & ACC_INTERFACE)) {
1895 char logtext[MAXLOGTEXT];
1896 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1897 utf_sprint(logtext + strlen(logtext), c->name);
1898 error("%s",logtext);
1902 for (i = 0; i < c->interfacescount; i++) {
1903 s4 h2 = class_highestinterface(c->interfaces[i]);
1911 /* class_addinterface **********************************************************
1913 Is needed by class_link for adding a VTBL to a class. All interfaces
1914 implemented by ic are added as well.
1916 *******************************************************************************/
1918 static void class_addinterface (classinfo *c, classinfo *ic)
1922 vftbl *vftbl = c->vftbl;
1924 if (i >= vftbl->interfacetablelength)
1925 panic ("Inernal error: interfacetable overflow");
1926 if (vftbl->interfacetable[-i])
1929 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1930 vftbl->interfacevftbllength[i] = 1;
1931 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1932 vftbl->interfacetable[-i][0] = NULL;
1935 vftbl->interfacevftbllength[i] = ic->methodscount;
1936 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1939 count_vftbl_len += sizeof(methodptr) *
1940 (ic->methodscount + (ic->methodscount == 0));
1943 for (j=0; j<ic->methodscount; j++) {
1946 for (m = 0; m < sc->methodscount; m++) {
1947 methodinfo *mi = &(sc->methods[m]);
1948 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1949 vftbl->interfacetable[-i][j] =
1950 vftbl->table[mi->vftblindex];
1960 for (j = 0; j < ic->interfacescount; j++)
1961 class_addinterface(c, ic->interfaces[j]);
1965 /******************* Function: class_new_array *********************************
1967 This function is called by class_new to setup an array class.
1969 *******************************************************************************/
1971 void class_new_array(classinfo *c)
1973 classinfo *comp = NULL;
1977 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1979 /* Array classes are not loaded from classfiles. */
1980 list_remove(&unloadedclasses, c);
1982 /* Check array class name */
1983 namelen = c->name->blength;
1984 if (namelen < 2 || c->name->text[0] != '[')
1985 panic("Invalid array class name");
1987 /* Check the component type */
1988 switch (c->name->text[1]) {
1990 /* c is an array of arrays. We have to create the component class. */
1991 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1995 /* c is an array of objects. */
1996 if (namelen < 4 || c->name->text[namelen - 1] != ';')
1997 panic("Invalid array class name");
1998 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2002 /* Setup the array class */
2003 c->super = class_java_lang_Object;
2004 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2006 c->interfacescount = 2;
2007 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
2008 c->interfaces[0] = class_java_lang_Cloneable;
2009 c->interfaces[1] = class_java_io_Serializable;
2011 c->methodscount = 1;
2012 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
2015 memset(clone, 0, sizeof(methodinfo));
2016 clone->flags = ACC_PUBLIC; /* XXX protected? */
2017 clone->name = utf_new_char("clone");
2018 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2020 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2021 clone->monoPoly = MONO; /* XXX should be poly? */
2023 /* XXX: field: length? */
2025 /* The array class has to be linked */
2026 list_addlast(&unlinkedclasses,c);
2029 * Array classes which are created after the other classes have been
2030 * loaded and linked are linked explicitely.
2035 loader_load(c->name); /* XXX handle errors */
2039 /****************** Function: class_link_array *********************************
2041 This function is called by class_link to create the
2042 arraydescriptor for an array class.
2044 This function returns NULL if the array cannot be linked because
2045 the component type has not been linked yet.
2047 *******************************************************************************/
2049 static arraydescriptor *class_link_array(classinfo *c)
2051 classinfo *comp = NULL;
2052 int namelen = c->name->blength;
2053 arraydescriptor *desc;
2056 /* Check the component type */
2057 switch (c->name->text[1]) {
2059 /* c is an array of arrays. */
2060 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2061 if (!comp) panic("Could not find component array class.");
2065 /* c is an array of objects. */
2066 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2067 if (!comp) panic("Could not find component class.");
2071 /* If the component type has not been linked return NULL */
2072 if (comp && !comp->linked)
2075 /* Allocate the arraydescriptor */
2076 desc = NEW(arraydescriptor);
2079 /* c is an array of references */
2080 desc->arraytype = ARRAYTYPE_OBJECT;
2081 desc->componentsize = sizeof(void*);
2082 desc->dataoffset = OFFSET(java_objectarray,data);
2084 compvftbl = comp->vftbl;
2086 panic("Component class has no vftbl");
2087 desc->componentvftbl = compvftbl;
2089 if (compvftbl->arraydesc) {
2090 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2091 if (compvftbl->arraydesc->dimension >= 255)
2092 panic("Creating array of dimension >255");
2093 desc->dimension = compvftbl->arraydesc->dimension + 1;
2094 desc->elementtype = compvftbl->arraydesc->elementtype;
2097 desc->elementvftbl = compvftbl;
2098 desc->dimension = 1;
2099 desc->elementtype = ARRAYTYPE_OBJECT;
2103 /* c is an array of a primitive type */
2104 switch (c->name->text[1]) {
2105 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2106 desc->dataoffset = OFFSET(java_booleanarray,data);
2107 desc->componentsize = sizeof(u1);
2110 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2111 desc->dataoffset = OFFSET(java_bytearray,data);
2112 desc->componentsize = sizeof(u1);
2115 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2116 desc->dataoffset = OFFSET(java_chararray,data);
2117 desc->componentsize = sizeof(u2);
2120 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2121 desc->dataoffset = OFFSET(java_doublearray,data);
2122 desc->componentsize = sizeof(double);
2125 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2126 desc->dataoffset = OFFSET(java_floatarray,data);
2127 desc->componentsize = sizeof(float);
2130 case 'I': desc->arraytype = ARRAYTYPE_INT;
2131 desc->dataoffset = OFFSET(java_intarray,data);
2132 desc->componentsize = sizeof(s4);
2135 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2136 desc->dataoffset = OFFSET(java_longarray,data);
2137 desc->componentsize = sizeof(s8);
2140 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2141 desc->dataoffset = OFFSET(java_shortarray,data);
2142 desc->componentsize = sizeof(s2);
2146 panic("Invalid array class name");
2149 desc->componentvftbl = NULL;
2150 desc->elementvftbl = NULL;
2151 desc->dimension = 1;
2152 desc->elementtype = desc->arraytype;
2159 /********************** Function: class_link ***********************************
2161 Tries to link a class. The super class and every implemented interface must
2162 already have been linked. The function calculates the length in bytes that
2163 an instance of this class requires as well as the VTBL for methods and
2166 If the class can be linked, it is removed from the list 'unlinkedclasses'
2167 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2170 Attention: If cyclical class definitions are encountered, the program gets
2171 into an infinite loop (we'll have to work that out)
2173 *******************************************************************************/
2175 void class_link(classinfo *c)
2177 s4 supervftbllength; /* vftbllegnth of super class */
2178 s4 vftbllength; /* vftbllength of current class */
2179 s4 interfacetablelength; /* interface table length */
2180 classinfo *super = c->super; /* super class */
2181 classinfo *ic, *c2; /* intermediate class variables */
2182 vftbl *v; /* vftbl of current class */
2183 s4 i; /* interface/method/field counter */
2184 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2187 /* check if all superclasses are already linked, if not put c at end of
2188 unlinked list and return. Additionally initialize class fields. */
2190 /* check interfaces */
2192 for (i = 0; i < c->interfacescount; i++) {
2193 ic = c->interfaces[i];
2195 list_remove(&unlinkedclasses, c);
2196 list_addlast(&unlinkedclasses, c);
2199 if ((ic->flags & ACC_INTERFACE) == 0) {
2200 dolog("Specified interface is not declared as interface:");
2204 panic("Specified interface is not declared as interface");
2208 /* check super class */
2210 if (super == NULL) { /* class java.long.Object */
2212 c->classUsed = USED; /* Object class is always used CO-RT*/
2214 c->instancesize = sizeof(java_objectheader);
2216 vftbllength = supervftbllength = 0;
2218 c->finalizer = NULL;
2221 if (!super->linked) {
2222 list_remove(&unlinkedclasses, c);
2223 list_addlast(&unlinkedclasses, c);
2227 if ((super->flags & ACC_INTERFACE) != 0)
2228 panic("Interface specified as super class");
2230 /* handle array classes */
2231 /* The component class must have been linked already. */
2232 if (c->name->text[0] == '[')
2233 if ((arraydesc = class_link_array(c)) == NULL) {
2234 list_remove(&unlinkedclasses, c);
2235 list_addlast(&unlinkedclasses, c);
2239 /* Don't allow extending final classes */
2240 if ((super->flags & ACC_FINAL) != 0)
2241 panic("Trying to extend final class");
2243 if (c->flags & ACC_INTERFACE)
2244 c->index = interfaceindex++;
2246 c->index = super->index + 1;
2248 c->instancesize = super->instancesize;
2250 vftbllength = supervftbllength = super->vftbl->vftbllength;
2252 c->finalizer = super->finalizer;
2257 char logtext[MAXLOGTEXT];
2258 sprintf(logtext, "Linking Class: ");
2259 utf_sprint(logtext + strlen(logtext), c->name );
2263 /* compute vftbl length */
2265 for (i = 0; i < c->methodscount; i++) {
2266 methodinfo *m = &(c->methods[i]);
2268 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2269 classinfo *sc = super;
2272 for (j = 0; j < sc->methodscount; j++) {
2273 if (method_canoverwrite(m, &(sc->methods[j]))) {
2274 if ((sc->methods[j].flags & ACC_FINAL) != 0)
2275 panic("Trying to overwrite final method");
2276 m->vftblindex = sc->methods[j].vftblindex;
2277 goto foundvftblindex;
2282 m->vftblindex = (vftbllength++);
2288 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2291 /* compute interfacetable length */
2293 interfacetablelength = 0;
2296 for (i = 0; i < c2->interfacescount; i++) {
2297 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2298 if (h > interfacetablelength)
2299 interfacetablelength = h;
2304 /* allocate virtual function table */
2306 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2307 (vftbllength - 1) + sizeof(methodptr*) *
2308 (interfacetablelength - (interfacetablelength > 0)));
2309 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2310 (interfacetablelength > 1));
2311 c->header.vftbl = c->vftbl = v;
2313 v->vftbllength = vftbllength;
2314 v->interfacetablelength = interfacetablelength;
2315 v->arraydesc = arraydesc;
2317 /* store interface index in vftbl */
2318 if (c->flags & ACC_INTERFACE)
2319 v->baseval = -(c->index);
2321 /* copy virtual function table of super class */
2323 for (i = 0; i < supervftbllength; i++)
2324 v->table[i] = super->vftbl->table[i];
2326 /* add method stubs into virtual function table */
2328 for (i = 0; i < c->methodscount; i++) {
2329 methodinfo *m = &(c->methods[i]);
2330 if (!(m->flags & ACC_STATIC)) {
2331 v->table[m->vftblindex] = m->stubroutine;
2335 /* compute instance size and offset of each field */
2337 for (i = 0; i < c->fieldscount; i++) {
2339 fieldinfo *f = &(c->fields[i]);
2341 if (!(f->flags & ACC_STATIC) ) {
2342 dsize = desc_typesize(f->descriptor);
2343 c->instancesize = ALIGN(c->instancesize, dsize);
2344 f->offset = c->instancesize;
2345 c->instancesize += dsize;
2349 /* initialize interfacetable and interfacevftbllength */
2351 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2354 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2357 for (i = 0; i < interfacetablelength; i++) {
2358 v->interfacevftbllength[i] = 0;
2359 v->interfacetable[-i] = NULL;
2362 /* add interfaces */
2364 for (c2 = c; c2 != NULL; c2 = c2->super)
2365 for (i = 0; i < c2->interfacescount; i++) {
2366 class_addinterface(c, c2->interfaces[i]);
2369 /* add finalizer method (not for java.lang.Object) */
2371 if (super != NULL) {
2373 static utf *finame = NULL;
2374 static utf *fidesc = NULL;
2377 finame = utf_finalize;
2379 fidesc = utf_fidesc;
2381 fi = class_findmethod(c, finame, fidesc);
2383 if (!(fi->flags & ACC_STATIC)) {
2393 list_remove(&unlinkedclasses, c);
2394 list_addlast(&linkedclasses, c);
2398 /******************* Function: class_freepool **********************************
2400 Frees all resources used by this classes Constant Pool.
2402 *******************************************************************************/
2404 static void class_freecpool (classinfo *c)
2410 for (idx=0; idx < c->cpcount; idx++) {
2411 tag = c->cptags[idx];
2412 info = c->cpinfos[idx];
2416 case CONSTANT_Fieldref:
2417 case CONSTANT_Methodref:
2418 case CONSTANT_InterfaceMethodref:
2419 FREE (info, constant_FMIref);
2421 case CONSTANT_Integer:
2422 FREE (info, constant_integer);
2424 case CONSTANT_Float:
2425 FREE (info, constant_float);
2428 FREE (info, constant_long);
2430 case CONSTANT_Double:
2431 FREE (info, constant_double);
2433 case CONSTANT_NameAndType:
2434 FREE (info, constant_nameandtype);
2440 MFREE (c -> cptags, u1, c -> cpcount);
2441 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2445 /*********************** Function: class_free **********************************
2447 Frees all resources used by the class.
2449 *******************************************************************************/
2451 static void class_free(classinfo *c)
2458 MFREE(c->interfaces, classinfo*, c->interfacescount);
2460 for (i = 0; i < c->fieldscount; i++)
2461 field_free(&(c->fields[i]));
2463 for (i = 0; i < c->methodscount; i++)
2464 method_free(&(c->methods[i]));
2465 MFREE(c->methods, methodinfo, c->methodscount);
2467 if ((v = c->vftbl) != NULL) {
2469 mem_free(v->arraydesc,sizeof(arraydescriptor));
2471 for (i = 0; i < v->interfacetablelength; i++) {
2472 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2474 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2476 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2477 sizeof(methodptr*) * (v->interfacetablelength -
2478 (v->interfacetablelength > 0));
2479 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2480 (v->interfacetablelength > 1));
2484 if (c->innerclasscount)
2485 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2487 /* if (c->classvftbl)
2488 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2494 /************************* Function: class_findfield ***************************
2496 Searches a 'classinfo' structure for a field having the given name and
2499 *******************************************************************************/
2501 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2505 for (i = 0; i < c->fieldscount; i++) {
2506 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2507 return &(c->fields[i]);
2510 panic("Can not find field given in CONSTANT_Fieldref");
2512 /* keep compiler happy */
2517 /************************* Function: class_findmethod **************************
2519 Searches a 'classinfo' structure for a method having the given name and
2520 type and returns the index in the class info structure.
2521 If type is NULL, it is ignored.
2523 *******************************************************************************/
2525 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2528 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2530 int buffer_len, pos;
2532 #ifdef JOWENN_DEBUG1
2535 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2537 buffer = MNEW(char, buffer_len);
2539 strcpy(buffer, "class_findmethod: method:");
2540 utf_sprint(buffer + strlen(buffer), name);
2541 strcpy(buffer + strlen(buffer), ", desc: ");
2542 utf_sprint(buffer + strlen(buffer), desc);
2543 strcpy(buffer + strlen(buffer), ", classname: ");
2544 utf_sprint(buffer + strlen(buffer), c->name);
2548 MFREE(buffer, char, buffer_len);
2550 for (i = 0; i < c->methodscount; i++) {
2551 #ifdef JOWENN_DEBUG2
2553 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2555 buffer = MNEW(char, buffer_len);
2557 strcpy(buffer, "class_findmethod: comparing to method:");
2558 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2559 strcpy(buffer + strlen(buffer), ", desc: ");
2560 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2564 MFREE(buffer, char, buffer_len);
2568 if ((c->methods[i].name == name) && ((desc == NULL) ||
2569 (c->methods[i].descriptor == desc))) {
2574 #ifdef JOWENN_DEBUG2
2575 class_showconstantpool(c);
2576 log_text("class_findmethod: returning NULL");
2583 /************************* Function: class_findmethod **************************
2585 Searches a 'classinfo' structure for a method having the given name and
2587 If type is NULL, it is ignored.
2589 *******************************************************************************/
2591 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2595 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2597 int buffer_len, pos;
2599 #ifdef JOWENN_DEBUG1
2602 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2604 buffer = MNEW(char, buffer_len);
2606 strcpy(buffer, "class_findmethod: method:");
2607 utf_sprint(buffer + strlen(buffer), name);
2608 strcpy(buffer + strlen(buffer), ", desc: ");
2609 utf_sprint(buffer + strlen(buffer), desc);
2610 strcpy(buffer + strlen(buffer), ", classname: ");
2611 utf_sprint(buffer + strlen(buffer), c->name);
2615 MFREE(buffer, char, buffer_len);
2617 for (i = 0; i < c->methodscount; i++) {
2618 #ifdef JOWENN_DEBUG2
2620 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2622 buffer = MNEW(char, buffer_len);
2624 strcpy(buffer, "class_findmethod: comparing to method:");
2625 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2626 strcpy(buffer + strlen(buffer), ", desc: ");
2627 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2631 MFREE(buffer, char, buffer_len);
2634 if ((c->methods[i].name == name) && ((desc == NULL) ||
2635 (c->methods[i].descriptor == desc))) {
2636 return &(c->methods[i]);
2639 #ifdef JOWENN_DEBUG2
2640 class_showconstantpool(c);
2641 log_text("class_findmethod: returning NULL");
2646 s4 idx=class_findmethodIndex(c, name, desc);
2647 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2648 if (idx == -1) return NULL;
2650 return &(c->methods[idx]);
2654 /*********************** Function: class_fetchmethod **************************
2656 like class_findmethod, but aborts with an error if the method is not found
2658 *******************************************************************************/
2660 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2663 mi = class_findmethod(c, name, desc);
2666 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2667 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2668 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2669 panic("Method not found");
2676 /************************* Function: class_findmethod_approx ******************
2678 like class_findmethod but ignores the return value when comparing the
2681 *******************************************************************************/
2683 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2687 for (i = 0; i < c->methodscount; i++) {
2688 if (c->methods[i].name == name) {
2689 utf *meth_descr = c->methods[i].descriptor;
2693 return &(c->methods[i]);
2695 if (desc->blength <= meth_descr->blength) {
2696 /* current position in utf text */
2697 char *desc_utf_ptr = desc->text;
2698 char *meth_utf_ptr = meth_descr->text;
2699 /* points behind utf strings */
2700 char *desc_end = utf_end(desc);
2701 char *meth_end = utf_end(meth_descr);
2704 /* compare argument types */
2705 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2707 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2708 break; /* no match */
2711 return &(c->methods[i]); /* all parameter types equal */
2721 /***************** Function: class_resolvemethod_approx ***********************
2723 Searches a class and every super class for a method (without paying
2724 attention to the return value)
2726 *******************************************************************************/
2728 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2731 /* search for method (ignore returntype) */
2732 methodinfo *m = class_findmethod_approx(c, name, desc);
2735 /* search superclass */
2743 /************************* Function: class_resolvemethod ***********************
2745 Searches a class and every super class for a method.
2747 *******************************************************************************/
2749 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2752 methodinfo *m = class_findmethod(c, name, desc);
2754 /* search superclass */
2762 /************************* Function: class_issubclass **************************
2764 Checks if sub is a descendant of super.
2766 *******************************************************************************/
2768 bool class_issubclass(classinfo *sub, classinfo *super)
2771 if (!sub) return false;
2772 if (sub == super) return true;
2778 /****************** Initialization function for classes ******************
2780 In Java, every class can have a static initialization function. This
2781 function has to be called BEFORE calling other methods or accessing static
2784 *******************************************************************************/
2786 void class_init(classinfo *c)
2794 if (!makeinitializations)
2799 c->initialized = true;
2802 count_class_inits++;
2805 /* initialize super class */
2808 char logtext[MAXLOGTEXT];
2809 sprintf(logtext, "Initialize super class ");
2810 utf_sprint(logtext + strlen(logtext), c->super->name);
2811 sprintf(logtext + strlen(logtext), " from ");
2812 utf_sprint(logtext + strlen(logtext), c->name);
2815 class_init(c->super);
2818 /* initialize interface classes */
2819 for (i = 0; i < c->interfacescount; i++) {
2821 char logtext[MAXLOGTEXT];
2822 sprintf(logtext, "Initialize interface class ");
2823 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2824 sprintf(logtext + strlen(logtext), " from ");
2825 utf_sprint(logtext + strlen(logtext), c->name);
2828 class_init(c->interfaces[i]); /* real */
2831 m = class_findmethod(c, utf_clinit, utf_fidesc);
2834 char logtext[MAXLOGTEXT];
2835 sprintf(logtext, "Class ");
2836 utf_sprint(logtext + strlen(logtext), c->name);
2837 sprintf(logtext + strlen(logtext), " has no initializer");
2840 /* goto callinitialize;*/
2844 if (!(m->flags & ACC_STATIC))
2845 panic("Class initializer is not static!");
2848 char logtext[MAXLOGTEXT];
2849 sprintf(logtext, "Starting initializer for class: ");
2850 utf_sprint(logtext + strlen(logtext), c->name);
2859 /* now call the initializer */
2860 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2863 assert(blockInts == 0);
2867 /* we have to throw an exception */
2868 if (*exceptionptr) {
2869 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2870 printf("Caused by: ");
2871 utf_display((*exceptionptr)->vftbl->class->name);
2878 char logtext[MAXLOGTEXT];
2879 sprintf(logtext, "Finished initializer for class: ");
2880 utf_sprint(logtext + strlen(logtext), c->name);
2884 if (c->name == utf_systemclass) {
2885 /* class java.lang.System requires explicit initialization */
2888 printf("#### Initializing class System");
2890 /* find initializing method */
2891 m = class_findmethod(c,
2892 utf_initsystemclass,
2896 /* no method found */
2897 /* printf("initializeSystemClass failed"); */
2906 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2909 assert(blockInts == 0);
2913 if (*exceptionptr) {
2914 printf("#### initializeSystemClass has thrown: ");
2915 utf_display((*exceptionptr)->vftbl->class->name);
2923 /********* Function: find_class_method_constant *********/
2925 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2930 for (i=0; i<c->cpcount; i++) {
2932 e = c -> cpinfos [i];
2935 switch (c -> cptags [i]) {
2936 case CONSTANT_Methodref:
2938 constant_FMIref *fmi = e;
2939 if ( (fmi->class->name == c1)
2940 && (fmi->name == m1)
2941 && (fmi->descriptor == d1)) {
2948 case CONSTANT_InterfaceMethodref:
2950 constant_FMIref *fmi = e;
2951 if ( (fmi->class->name == c1)
2952 && (fmi->name == m1)
2953 && (fmi->descriptor == d1)) {
2967 void class_showconstanti(classinfo *c, int ii)
2973 printf ("#%d: ", (int) i);
2975 switch (c->cptags [i]) {
2976 case CONSTANT_Class:
2977 printf("Classreference -> ");
2978 utf_display(((classinfo*)e)->name);
2981 case CONSTANT_Fieldref:
2982 printf("Fieldref -> "); goto displayFMIi;
2983 case CONSTANT_Methodref:
2984 printf("Methodref -> "); goto displayFMIi;
2985 case CONSTANT_InterfaceMethodref:
2986 printf("InterfaceMethod -> "); goto displayFMIi;
2989 constant_FMIref *fmi = e;
2990 utf_display(fmi->class->name);
2992 utf_display(fmi->name);
2994 utf_display(fmi->descriptor);
2998 case CONSTANT_String:
2999 printf("String -> ");
3002 case CONSTANT_Integer:
3003 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3005 case CONSTANT_Float:
3006 printf("Float -> %f", ((constant_float*)e)->value);
3008 case CONSTANT_Double:
3009 printf("Double -> %f", ((constant_double*)e)->value);
3013 u8 v = ((constant_long*)e)->value;
3015 printf("Long -> %ld", (long int) v);
3017 printf("Long -> HI: %ld, LO: %ld\n",
3018 (long int) v.high, (long int) v.low);
3022 case CONSTANT_NameAndType:
3024 constant_nameandtype *cnt = e;
3025 printf("NameAndType: ");
3026 utf_display(cnt->name);
3028 utf_display(cnt->descriptor);
3036 panic("Invalid type of ConstantPool-Entry");
3043 void class_showconstantpool (classinfo *c)
3048 printf ("---- dump of constant pool ----\n");
3050 for (i=0; i<c->cpcount; i++) {
3051 printf ("#%d: ", (int) i);
3053 e = c -> cpinfos [i];
3056 switch (c -> cptags [i]) {
3057 case CONSTANT_Class:
3058 printf ("Classreference -> ");
3059 utf_display ( ((classinfo*)e) -> name );
3062 case CONSTANT_Fieldref:
3063 printf ("Fieldref -> "); goto displayFMI;
3064 case CONSTANT_Methodref:
3065 printf ("Methodref -> "); goto displayFMI;
3066 case CONSTANT_InterfaceMethodref:
3067 printf ("InterfaceMethod -> "); goto displayFMI;
3070 constant_FMIref *fmi = e;
3071 utf_display ( fmi->class->name );
3073 utf_display ( fmi->name);
3075 utf_display ( fmi->descriptor );
3079 case CONSTANT_String:
3080 printf ("String -> ");
3083 case CONSTANT_Integer:
3084 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3086 case CONSTANT_Float:
3087 printf ("Float -> %f", ((constant_float*)e) -> value);
3089 case CONSTANT_Double:
3090 printf ("Double -> %f", ((constant_double*)e) -> value);
3094 u8 v = ((constant_long*)e) -> value;
3096 printf ("Long -> %ld", (long int) v);
3098 printf ("Long -> HI: %ld, LO: %ld\n",
3099 (long int) v.high, (long int) v.low);
3103 case CONSTANT_NameAndType:
3105 constant_nameandtype *cnt = e;
3106 printf ("NameAndType: ");
3107 utf_display (cnt->name);
3109 utf_display (cnt->descriptor);
3113 printf ("Utf8 -> ");
3117 panic ("Invalid type of ConstantPool-Entry");
3127 /********** Function: class_showmethods (debugging only) *************/
3129 void class_showmethods (classinfo *c)
3133 printf ("--------- Fields and Methods ----------------\n");
3134 printf ("Flags: "); printflags (c->flags); printf ("\n");
3136 printf ("This: "); utf_display (c->name); printf ("\n");
3138 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3140 printf ("Index: %d\n", c->index);
3142 printf ("interfaces:\n");
3143 for (i=0; i < c-> interfacescount; i++) {
3145 utf_display (c -> interfaces[i] -> name);
3146 printf (" (%d)\n", c->interfaces[i] -> index);
3149 printf ("fields:\n");
3150 for (i=0; i < c -> fieldscount; i++) {
3151 field_display (&(c -> fields[i]));
3154 printf ("methods:\n");
3155 for (i=0; i < c -> methodscount; i++) {
3156 methodinfo *m = &(c->methods[i]);
3157 if ( !(m->flags & ACC_STATIC))
3158 printf ("vftblindex: %d ", m->vftblindex);
3160 method_display ( m );
3164 printf ("Virtual function table:\n");
3165 for (i=0; i<c->vftbl->vftbllength; i++) {
3166 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3173 /******************************************************************************/
3174 /******************* General functions for the class loader *******************/
3175 /******************************************************************************/
3177 /********************* Function: loader_load ***********************************
3179 Loads and links the class desired class and each class and interface
3181 Returns: a pointer to this class
3183 *******************************************************************************/
3185 static int loader_load_running = 0;
3187 classinfo *loader_load(utf *topname)
3193 classinfo *notlinkable;
3195 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3196 pthread_mutex_lock(&compiler_mutex);
3199 /* avoid recursive calls */
3200 if (loader_load_running)
3201 return class_new(topname);
3203 loader_load_running++;
3208 starttime = getcputime();
3210 top = class_new(topname);
3213 while ((c = list_first(&unloadedclasses))) {
3214 if (!class_load(c)) {
3216 dolog("Failed to load class");
3217 list_remove(&unloadedclasses, c);
3224 dolog("Linking...");
3226 /* XXX added a hack to break infinite linking loops. A better
3227 * linking algorithm would be nice. -Edwin */
3229 while ((c = list_first(&unlinkedclasses))) {
3234 else if (notlinkable == c) {
3235 /* We tried to link this class for the second time and
3236 * no other classes were linked in between, so we are
3240 dolog("Cannot resolve linking dependencies");
3243 throw_linkageerror_message(c->name);
3251 dolog("Linking done.");
3254 loader_compute_subclasses();
3257 if (getloadingtime) {
3258 stoptime = getcputime();
3259 loadingtime += (stoptime - starttime);
3263 loader_load_running--;
3265 /* check if a former loader_load call tried to load/link the class and
3266 failed. This is needed because the class didn't appear in the
3267 undloadclasses or unlinkedclasses list during this class. */
3270 if (linkverbose) dolog("Failed to load class (former call)");
3271 throw_noclassdeffounderror_message(top->name);
3274 } else if (!top->linked) {
3276 dolog("Failed to link class (former call)");
3277 throw_linkageerror_message(top->name);
3284 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3285 pthread_mutex_unlock(&compiler_mutex);
3288 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
3294 /****************** Function: loader_load_sysclass ****************************
3296 Loads and links the class desired class and each class and interface
3299 The pointer to the classinfo is stored in *top if top != NULL.
3300 The pointer is also returned.
3302 If the class could not be loaded the function aborts with an error.
3304 *******************************************************************************/
3306 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3310 if ((cls = loader_load(topname)) == NULL) {
3311 log_plain("Could not load important system class: ");
3312 log_plain_utf(topname);
3314 panic("Could not load important system class");
3317 if (top) *top = cls;
3323 /**************** function: create_primitive_classes ***************************
3325 create classes representing primitive types
3327 ********************************************************************************/
3330 void create_primitive_classes()
3334 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3335 /* create primitive class */
3336 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3337 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3338 c -> impldBy = NULL;
3340 /* prevent loader from loading primitive class */
3341 list_remove (&unloadedclasses, c);
3343 /* add to unlinked classes */
3344 list_addlast (&unlinkedclasses, c);
3345 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3348 primitivetype_table[i].class_primitive = c;
3350 /* create class for wrapping the primitive type */
3351 primitivetype_table[i].class_wrap =
3352 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3353 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3354 primitivetype_table[i].class_wrap -> impldBy = NULL;
3356 /* create the primitive array class */
3357 if (primitivetype_table[i].arrayname) {
3358 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3359 primitivetype_table[i].arrayclass = c;
3361 if (!c->linked) class_link(c);
3362 primitivetype_table[i].arrayvftbl = c->vftbl;
3367 /**************** function: class_primitive_from_sig ***************************
3369 return the primitive class indicated by the given signature character
3371 If the descriptor does not indicate a valid primitive type the
3372 return value is NULL.
3374 ********************************************************************************/
3376 classinfo *class_primitive_from_sig(char sig)
3379 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3380 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3381 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3382 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3383 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3384 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3385 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3386 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3387 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3392 /****************** function: class_from_descriptor ****************************
3394 return the class indicated by the given descriptor
3396 utf_ptr....first character of descriptor
3397 end_ptr....first character after the end of the string
3398 next.......if non-NULL, *next is set to the first character after
3399 the descriptor. (Undefined if an error occurs.)
3401 mode.......a combination (binary or) of the following flags:
3403 (Flags marked with * are the default settings.)
3405 What to do if a reference type descriptor is parsed successfully:
3407 CLASSLOAD_SKIP...skip it and return something != NULL
3408 * CLASSLOAD_NEW....get classinfo * via class_new
3409 CLASSLOAD_LOAD...get classinfo * via loader_load
3411 How to handle primitive types:
3413 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3414 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3416 How to handle "V" descriptors:
3418 * CLASSLOAD_VOID.....handle it like other primitive types
3419 CLASSLOAD_NOVOID...treat it as an error
3421 How to deal with extra characters after the end of the
3424 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3425 CLASSLOAD_CHECKEND.....treat them as an error
3427 How to deal with errors:
3429 * CLASSLOAD_PANIC....abort execution with an error message
3430 CLASSLOAD_NOPANIC..return NULL on error
3432 ********************************************************************************/
3434 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3435 char **next, int mode)
3437 char *start = utf_ptr;
3441 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3443 if (mode & CLASSLOAD_CHECKEND)
3444 error |= (utf_ptr != end_ptr);
3447 if (next) *next = utf_ptr;
3451 if (mode & CLASSLOAD_NOVOID)
3462 return (mode & CLASSLOAD_NULLPRIMITIVE)
3464 : class_primitive_from_sig(*start);
3471 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3472 name = utf_new(start,utf_ptr-start);
3473 return (mode & CLASSLOAD_LOAD)
3474 ? loader_load(name) : class_new(name); /* XXX */
3478 /* An error occurred */
3479 if (mode & CLASSLOAD_NOPANIC)
3482 log_plain("Invalid descriptor at beginning of '");
3483 log_plain_utf(utf_new(start, end_ptr-start));
3487 panic("Invalid descriptor");
3489 /* keep compiler happy */
3494 /******************* function: type_from_descriptor ****************************
3496 return the basic type indicated by the given descriptor
3498 This function parses a descriptor and returns its basic type as
3499 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3501 cls...if non-NULL the referenced variable is set to the classinfo *
3502 returned by class_from_descriptor.
3504 For documentation of the arguments utf_ptr, end_ptr, next and mode
3505 see class_from_descriptor. The only difference is that
3506 type_from_descriptor always uses CLASSLOAD_PANIC.
3508 ********************************************************************************/
3510 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3511 char **next, int mode)
3514 if (!cls) cls = &mycls;
3515 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3532 return TYPE_ADDRESS;
3536 /*************** function: create_pseudo_classes *******************************
3538 create pseudo classes used by the typechecker
3540 ********************************************************************************/
3542 static void create_pseudo_classes()
3544 /* pseudo class for Arraystubs (extends java.lang.Object) */
3546 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3547 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3549 pseudo_class_Arraystub->super = class_java_lang_Object;
3550 pseudo_class_Arraystub->interfacescount = 2;
3551 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3552 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3553 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3555 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3556 class_link(pseudo_class_Arraystub);
3558 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3560 /* pseudo class representing the null type */
3562 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3563 list_remove(&unloadedclasses, pseudo_class_Null);
3565 pseudo_class_Null->super = class_java_lang_Object;
3567 list_addlast(&unlinkedclasses, pseudo_class_Null);
3568 class_link(pseudo_class_Null);
3570 /* pseudo class representing new uninitialized objects */
3572 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3573 list_remove(&unloadedclasses, pseudo_class_New);
3575 pseudo_class_New->super = class_java_lang_Object;
3577 list_addlast(&unlinkedclasses, pseudo_class_New);
3578 class_link(pseudo_class_New);
3582 /********************** Function: loader_init **********************************
3584 Initializes all lists and loads all classes required for the system or the
3587 *******************************************************************************/
3589 void loader_init(u1 *stackbottom)
3593 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3594 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3595 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3597 /* create utf-symbols for pointer comparison of frequently used strings */
3598 utf_innerclasses = utf_new_char("InnerClasses");
3599 utf_constantvalue = utf_new_char("ConstantValue");
3600 utf_code = utf_new_char("Code");
3601 utf_finalize = utf_new_char("finalize");
3602 utf_fidesc = utf_new_char("()V");
3603 utf_init = utf_new_char("<init>");
3604 utf_clinit = utf_new_char("<clinit>");
3605 utf_initsystemclass = utf_new_char("initializeSystemClass");
3606 utf_systemclass = utf_new_char("java/lang/System");
3607 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3608 utf_initialize = utf_new_char("initialize");
3609 utf_initializedesc = utf_new_char("(I)V");
3611 utf_vmclass = utf_new_char("java/lang/VMClass");
3612 utf_java_lang_Object= utf_new_char("java/lang/Object");
3614 array_packagename = utf_new_char("<the array package>");
3616 /* create some important classes */
3617 /* These classes have to be created now because the classinfo
3618 * pointers are used in the loading code.
3620 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3621 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3622 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3623 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3625 if (verbose) log_text("loader_init: java/lang/Object");
3626 /* load the classes which were created above */
3627 loader_load_sysclass(NULL, class_java_lang_Object->name);
3629 loader_inited = 1; /*JOWENN*/
3631 loader_load_sysclass(&class_java_lang_Throwable,
3632 utf_new_char("java/lang/Throwable"));
3634 if (verbose) log_text("loader_init: loader_load: java/lang/ClassCastException");
3635 loader_load_sysclass(&class_java_lang_ClassCastException,
3636 utf_new_char ("java/lang/ClassCastException"));
3637 loader_load_sysclass(&class_java_lang_NullPointerException,
3638 utf_new_char ("java/lang/NullPointerException"));
3639 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3640 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3641 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3642 utf_new_char ("java/lang/NegativeArraySizeException"));
3643 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3644 utf_new_char ("java/lang/OutOfMemoryError"));
3645 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3646 utf_new_char ("java/lang/ArrayStoreException"));
3647 loader_load_sysclass(&class_java_lang_ArithmeticException,
3648 utf_new_char ("java/lang/ArithmeticException"));
3649 loader_load_sysclass(&class_java_lang_ThreadDeath,
3650 utf_new_char ("java/lang/ThreadDeath"));
3652 /* create classes representing primitive types */
3653 create_primitive_classes();
3655 /* create classes used by the typechecker */
3656 create_pseudo_classes();
3658 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3659 stringtable_update();
3666 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3667 proto_java_lang_ClassCastException =
3668 builtin_new(class_java_lang_ClassCastException);
3670 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3672 proto_java_lang_NullPointerException =
3673 builtin_new(class_java_lang_NullPointerException);
3674 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3676 proto_java_lang_ArrayIndexOutOfBoundsException =
3677 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3679 proto_java_lang_NegativeArraySizeException =
3680 builtin_new(class_java_lang_NegativeArraySizeException);
3682 proto_java_lang_OutOfMemoryError =
3683 builtin_new(class_java_lang_OutOfMemoryError);
3685 proto_java_lang_ArithmeticException =
3686 builtin_new(class_java_lang_ArithmeticException);
3688 proto_java_lang_ArrayStoreException =
3689 builtin_new(class_java_lang_ArrayStoreException);
3691 proto_java_lang_ThreadDeath =
3692 builtin_new(class_java_lang_ThreadDeath);
3698 /********************* Function: loader_initclasses ****************************
3700 Initializes all loaded but uninitialized classes
3702 *******************************************************************************/
3705 /* XXX TWISTI: i think we do not need this */
3706 void loader_initclasses ()
3710 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3711 pthread_mutex_lock(&compiler_mutex);
3714 intsDisable(); /* schani */
3716 if (makeinitializations) {
3717 c = list_first(&linkedclasses);
3720 c = list_next(&linkedclasses, c);
3724 intsRestore(); /* schani */
3726 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3727 pthread_mutex_unlock(&compiler_mutex);
3733 static void loader_compute_class_values(classinfo *c)
3737 c->vftbl->baseval = ++classvalue;
3740 while (subs != NULL) {
3741 loader_compute_class_values(subs);
3742 subs = subs->nextsub;
3744 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3749 for (i = 0; i < c->index; i++)
3751 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3752 utf_display(c->name);
3759 void loader_compute_subclasses()
3763 intsDisable(); /* schani */
3765 c = list_first(&linkedclasses);
3767 if (!(c->flags & ACC_INTERFACE)) {
3771 c = list_next(&linkedclasses, c);
3774 c = list_first(&linkedclasses);
3776 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3777 c->nextsub = c->super->sub;
3780 c = list_next(&linkedclasses, c);
3784 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3787 loader_compute_class_values(class_java_lang_Object);
3788 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3792 intsRestore(); /* schani */
3796 /******************** function classloader_buffer ******************************
3798 sets buffer for reading classdata
3800 *******************************************************************************/
3802 void classload_buffer(u1 *buf, int len)
3805 classbuffer_size = len;
3806 classbuf_pos = buf - 1;
3810 /******************** Function: loader_close ***********************************
3814 *******************************************************************************/
3820 while ((c = list_first(&unloadedclasses))) {
3821 list_remove(&unloadedclasses, c);
3824 while ((c = list_first(&unlinkedclasses))) {
3825 list_remove(&unlinkedclasses, c);
3828 while ((c = list_first(&linkedclasses))) {
3829 list_remove(&linkedclasses, c);
3836 * These are local overrides for various environment variables in Emacs.
3837 * Please do not remove this and leave it at the end of the file, where
3838 * Emacs will automagically detect them.
3839 * ---------------------------------------------------------------------
3842 * indent-tabs-mode: t