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 1072 2004-05-19 17:20:12Z stefan $
50 #include "toolbox/memory.h"
51 #include "toolbox/logging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
54 #include "nat/java_lang_Throwable.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 */
79 /* utf-symbols for pointer comparison of frequently used strings */
81 static utf *utf_innerclasses; /* InnerClasses */
82 static utf *utf_constantvalue; /* ConstantValue */
83 static utf *utf_code; /* Code */
84 static utf *utf_exceptions; /* Exceptions */
85 static utf *utf_linenumbertable; /* LineNumberTable */
86 static utf *utf_sourcefile; /*SourceFile*/
87 static utf *utf_finalize; /* finalize */
88 static utf *utf_fidesc; /* ()V changed */
89 static utf *utf_init; /* <init> */
90 static utf *utf_clinit; /* <clinit> */
91 static utf *utf_initsystemclass; /* initializeSystemClass */
92 static utf *utf_systemclass; /* java/lang/System */
93 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
94 static utf *utf_vmclass; /* java/lang/VMClassLoader */
95 static utf *utf_initialize;
96 static utf *utf_initializedesc;
97 static utf *utf_java_lang_Object; /* java/lang/Object */
110 /* important system classes ***************************************************/
112 classinfo *class_java_lang_Object;
113 classinfo *class_java_lang_String;
115 classinfo *class_java_lang_Throwable;
116 classinfo *class_java_lang_Cloneable;
117 classinfo *class_java_io_Serializable;
119 /* Pseudo classes for the typechecker */
120 classinfo *pseudo_class_Arraystub = NULL;
121 classinfo *pseudo_class_Null = NULL;
122 classinfo *pseudo_class_New = NULL;
123 vftbl *pseudo_class_Arraystub_vftbl = NULL;
125 utf *array_packagename = NULL;
128 /********************************************************************
129 list of classpath entries (either filesystem directories or
131 ********************************************************************/
132 static classpath_info *classpath_entries=0;
135 /******************************************************************************
137 structure for primitive classes: contains the class for wrapping the
138 primitive type, the primitive class, the name of the class for wrapping,
139 the one character type signature and the name of the primitive class
141 ******************************************************************************/
143 /* CAUTION: Don't change the order of the types. This table is indexed
144 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
146 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
147 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
148 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
149 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
150 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
151 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
152 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
153 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
154 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
155 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
159 /* instances of important system classes **************************************/
161 java_objectheader *proto_java_lang_NullPointerException;
164 /************* functions for reading classdata *********************************
166 getting classdata in blocks of variable size
167 (8,16,32,64-bit integer or float)
169 *******************************************************************************/
171 static char *classpath = ""; /* searchpath for classfiles */
174 /* assert that at least <len> bytes are left to read */
175 /* <len> is limited to the range of non-negative s4 values */
177 #define ASSERT_LEFT(cb, len) \
179 if (((s4) (len)) < 0 || \
180 (((cb)->data + (cb)->size) - (cb)->pos - 1) < (len)) { \
181 char message[MAXLOGTEXT]; \
182 utf_sprint_classname(message, (cb)->class->name); \
183 sprintf(message + strlen(message), " (Truncated class file)"); \
185 new_exception_message(string_java_lang_ClassFormatError, \
187 throw_exception_exit(); \
192 /* transfer block of classfile data into a buffer */
194 #define suck_nbytes(buffer, cb, len) \
196 ASSERT_LEFT((cb), (len)); \
197 memcpy((buffer), (cb)->pos + 1, (len)); \
198 (cb)->pos += (len); \
202 /* skip block of classfile data */
204 #define skip_nbytes(cb, len) \
206 ASSERT_LEFT((cb), (len)); \
207 (cb)->pos += (len); \
211 inline u1 suck_u1(classbuffer *cb)
218 inline u2 suck_u2(classbuffer *cb)
222 return ((u2) a << 8) + (u2) b;
226 inline u4 suck_u4(classbuffer *cb)
232 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
235 #define suck_s8(a) (s8) suck_u8((a))
236 #define suck_s2(a) (s2) suck_u2((a))
237 #define suck_s4(a) (s4) suck_u4((a))
238 #define suck_s1(a) (s1) suck_u1((a))
241 /* get u8 from classfile data */
242 static u8 suck_u8(classbuffer *cb)
248 return (hi << 32) + lo;
251 v.high = suck_u4(cb);
258 /* get float from classfile data */
259 static float suck_float(classbuffer *cb)
267 for (i = 0; i < 4; i++)
268 buffer[3 - i] = suck_u1(cb);
270 memcpy((u1*) (&f), buffer, 4);
272 suck_nbytes((u1*) (&f), cb, 4);
275 PANICIF (sizeof(float) != 4, "Incompatible float-format");
281 /* get double from classfile data */
282 static double suck_double(classbuffer *cb)
290 for (i = 0; i < 8; i++)
291 buffer[7 - i] = suck_u1(cb);
293 memcpy((u1*) (&d), buffer, 8);
295 suck_nbytes((u1*) (&d), cb, 8);
298 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
304 /************************** function suck_init *********************************
306 called once at startup, sets the searchpath for the classfiles
308 *******************************************************************************/
310 void suck_init(char *cpath)
317 union classpath_info *tmp;
318 union classpath_info *insertAfter=0;
325 if (classpath_entries)
326 panic("suck_init should be called only once");
328 for (start = classpath; (*start) != '\0';) {
329 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
333 filenamelen = end - start;
336 if (strncasecmp(end - 3, "zip", 3) == 0 ||
337 strncasecmp(end - 3, "jar", 3) == 0) {
342 if (filenamelen >= (CLASSPATH_MAXFILENAME - 1))
343 panic("path length >= MAXFILENAME in suck_init");
346 filename = MNEW(char*, CLASSPATH_MAXFILENAME);
348 strncpy(filename, start, filenamelen);
349 filename[filenamelen + 1] = '\0';
354 unzFile uf = unzOpen(filename);
357 tmp = (union classpath_info *) NEW(classpath_info);
358 tmp->archive.type = CLASSPATH_ARCHIVE;
359 tmp->archive.uf = uf;
360 tmp->archive.next = 0;
364 panic("Zip/JAR not supported");
368 tmp = (union classpath_info *) NEW(classpath_info);
369 tmp->filepath.type = CLASSPATH_PATH;
370 tmp->filepath.next = 0;
372 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
373 filename[filenamelen] = '/';
374 filename[filenamelen + 1] = '\0';
378 tmp->filepath.filename = filename;
379 tmp->filepath.pathlen = filenamelen;
385 insertAfter->filepath.next = tmp;
388 classpath_entries = tmp;
400 MFREE(filename, char*, CLASSPATH_MAXFILENAME);
405 void create_all_classes()
409 for (cpi = classpath_entries; cpi != 0; cpi = cpi->filepath.next) {
410 #if defined(USE_ZLIB)
411 unz_file_info file_info;
412 if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
416 s = (unz_s *) cpi->archive.uf;
417 ce = s->cacao_dir_list;
420 (void) class_new(ce->name);
426 #if defined(USE_ZLIB)
433 /************************** function suck_start ********************************
435 returns true if classbuffer is already loaded or a file for the
436 specified class has succussfully been read in. All directories of
437 the searchpath are used to find the classfile (<classname>.class).
438 Returns false if no classfile is found and writes an error message.
440 *******************************************************************************/
442 classbuffer *suck_start(classinfo *c)
444 classpath_info *currPos;
447 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
454 utf_ptr = c->name->text;
456 while (utf_ptr < utf_end(c->name)) {
457 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
459 if ((ch <= ' ' || ch > 'z') && (ch != '/')) /* invalid character */
461 filename[filenamelen++] = ch;
464 strcpy(filename + filenamelen, ".class");
467 for (currPos = classpath_entries; currPos != 0; currPos = currPos->filepath.next) {
469 if (currPos->filepath.type == CLASSPATH_ARCHIVE) {
470 if (cacao_locate(currPos->archive.uf, c->name) == UNZ_OK) {
471 unz_file_info file_info;
472 /*log_text("Class found in zip file");*/
473 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
474 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
475 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
476 cb = NEW(classbuffer);
478 cb->size = file_info.uncompressed_size;
479 cb->data = MNEW(u1, cb->size);
480 cb->pos = cb->data - 1;
481 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
482 if (unzReadCurrentFile(currPos->archive.uf, cb->data, cb->size) == cb->size) {
483 unzCloseCurrentFile(currPos->archive.uf);
487 MFREE(cb->data, u1, cb->size);
488 FREE(cb, classbuffer);
489 log_text("Error while unzipping");
491 } else log_text("Error while opening file in archive");
492 } else log_text("Error while retrieving fileinfo");
494 unzCloseCurrentFile(currPos->archive.uf);
498 if ((currPos->filepath.pathlen + filenamelen) >= CLASSPATH_MAXFILENAME) continue;
499 strcpy(currPos->filepath.filename + currPos->filepath.pathlen, filename);
500 classfile = fopen(currPos->filepath.filename, "r");
501 if (classfile) { /* file exists */
503 /* determine size of classfile */
505 /* dolog("File: %s",filename); */
507 err = stat(currPos->filepath.filename, &buffer);
509 if (!err) { /* read classfile data */
510 cb = NEW(classbuffer);
512 cb->size = buffer.st_size;
513 cb->data = MNEW(u1, cb->size);
514 cb->pos = cb->data - 1;
515 fread(cb->data, 1, cb->size, classfile);
526 dolog("Warning: Can not open class file '%s'", filename);
533 /************************** function suck_stop *********************************
535 frees memory for buffer with classfile data.
536 Caution: this function may only be called if buffer has been allocated
537 by suck_start with reading a file
539 *******************************************************************************/
541 void suck_stop(classbuffer *cb)
545 MFREE(cb->data, u1, cb->size);
546 FREE(cb, classbuffer);
550 /******************************************************************************/
551 /******************* Some support functions ***********************************/
552 /******************************************************************************/
554 void fprintflags (FILE *fp, u2 f)
556 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
557 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
558 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
559 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
560 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
561 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
562 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
563 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
564 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
565 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
566 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
570 /********** internal function: printflags (only for debugging) ***************/
572 void printflags(u2 f)
574 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
575 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
576 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
577 if ( f & ACC_STATIC ) printf (" STATIC");
578 if ( f & ACC_FINAL ) printf (" FINAL");
579 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
580 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
581 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
582 if ( f & ACC_NATIVE ) printf (" NATIVE");
583 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
584 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
588 /************************* Function: skipattribute *****************************
590 skips a (1) 'attribute' structure in the class file
592 *******************************************************************************/
594 static void skipattribute(classbuffer *cb)
599 skip_nbytes(cb, len);
603 /********************** Function: skipattributebody ****************************
605 skips an attribute after the 16 bit reference to attribute_name has already
608 *******************************************************************************/
610 static void skipattributebody(classbuffer *cb)
614 skip_nbytes(cb, len);
618 /************************* Function: skipattributes ****************************
620 skips num attribute structures
622 *******************************************************************************/
624 static void skipattributes(classbuffer *cb, u4 num)
627 for (i = 0; i < num; i++)
632 /******************** function: innerclass_getconstant ************************
634 like class_getconstant, but if cptags is ZERO null is returned
636 *******************************************************************************/
638 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
640 /* invalid position in constantpool */
641 if (pos >= c->cpcount)
642 panic("Attempt to access constant outside range");
644 /* constantpool entry of type 0 */
648 /* check type of constantpool entry */
649 if (c->cptags[pos] != ctype) {
650 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
651 (int) ctype, (int) c->cptags[pos] );
654 return c->cpinfos[pos];
658 /************************ function: attribute_load ****************************
660 read attributes from classfile
662 *******************************************************************************/
664 static void attribute_load(classbuffer *cb, classinfo *c, u4 num)
668 for (i = 0; i < num; i++) {
669 /* retrieve attribute name */
670 utf *aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
672 if (aname == utf_innerclasses) {
673 /* innerclasses attribute */
675 if (c->innerclass != NULL)
676 panic("Class has more than one InnerClasses attribute");
678 /* skip attribute length */
680 /* number of records */
681 c->innerclasscount = suck_u2(cb);
682 /* allocate memory for innerclass structure */
683 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
685 for (j = 0; j < c->innerclasscount; j++) {
686 /* The innerclass structure contains a class with an encoded name,
687 its defining scope, its simple name and a bitmask of the access flags.
688 If an inner class is not a member, its outer_class is NULL,
689 if a class is anonymous, its name is NULL. */
691 innerclassinfo *info = c->innerclass + j;
693 info->inner_class = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); /* CONSTANT_Class_info index */
694 info->outer_class = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); /* CONSTANT_Class_info index */
695 info->name = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
696 info->flags = suck_u2(cb); /* access_flags bitmask */
698 } else if (aname==utf_sourcefile) {
700 /*log_text("source file attribute found");*/
701 c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
703 /* unknown attribute */
704 skipattributebody(cb);
710 /******************* function: checkfielddescriptor ****************************
712 checks whether a field-descriptor is valid and aborts otherwise
713 all referenced classes are inserted into the list of unloaded classes
715 *******************************************************************************/
717 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
719 class_from_descriptor(utf_ptr,end_pos,NULL,
721 | CLASSLOAD_NULLPRIMITIVE
723 | CLASSLOAD_CHECKEND);
725 /* XXX use the following if -noverify */
727 char *tstart; /* pointer to start of classname */
729 char *start = utf_ptr;
731 switch (*utf_ptr++) {
745 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
746 panic ("Ill formed descriptor");
750 panic ("Ill formed descriptor");
753 /* exceeding characters */
754 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
759 /******************* function checkmethoddescriptor ****************************
761 checks whether a method-descriptor is valid and aborts otherwise.
762 All referenced classes are inserted into the list of unloaded classes.
764 The number of arguments is returned. A long or double argument is counted
767 *******************************************************************************/
769 static int checkmethoddescriptor (utf *d)
771 char *utf_ptr = d->text; /* current position in utf text */
772 char *end_pos = utf_end(d); /* points behind utf string */
773 int argcount = 0; /* number of arguments */
775 /* method descriptor must start with parenthesis */
776 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
778 /* check arguments */
779 while (utf_ptr != end_pos && *utf_ptr != ')') {
780 /* We cannot count the this argument here because
781 * we don't know if the method is static. */
782 if (*utf_ptr == 'J' || *utf_ptr == 'D')
786 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
788 | CLASSLOAD_NULLPRIMITIVE
792 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
793 utf_ptr++; /* skip ')' */
795 class_from_descriptor(utf_ptr,end_pos,NULL,
797 | CLASSLOAD_NULLPRIMITIVE
798 | CLASSLOAD_CHECKEND);
801 panic("Invalid method descriptor: too many arguments");
805 /* XXX use the following if -noverify */
807 /* check arguments */
808 while ((c = *utf_ptr++) != ')') {
825 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
826 panic ("Ill formed method descriptor");
830 panic ("Ill formed methodtype-descriptor");
834 /* check returntype */
836 /* returntype void */
837 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
840 /* treat as field-descriptor */
841 checkfielddescriptor (utf_ptr,end_pos);
846 /***************** Function: print_arraydescriptor ****************************
848 Debugging helper for displaying an arraydescriptor
850 *******************************************************************************/
852 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
855 fprintf(file, "<NULL>");
860 if (desc->componentvftbl) {
861 if (desc->componentvftbl->class)
862 utf_fprint(file, desc->componentvftbl->class->name);
864 fprintf(file, "<no classinfo>");
870 if (desc->elementvftbl) {
871 if (desc->elementvftbl->class)
872 utf_fprint(file, desc->elementvftbl->class->name);
874 fprintf(file, "<no classinfo>");
878 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
879 desc->dataoffset, desc->componentsize);
883 /******************************************************************************/
884 /************************** Functions for fields ****************************/
885 /******************************************************************************/
888 /************************ Function: field_load *********************************
890 Load everything about a class field from the class file and fill a
891 'fieldinfo' structure. For static fields, space in the data segment is
894 *******************************************************************************/
896 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
898 static void field_load(classbuffer *cb, classinfo *c, fieldinfo *f)
902 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
904 f->flags = suck_u2(cb); /* ACC flags */
905 f->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* name of field */
906 f->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* JavaVM descriptor */
910 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
911 panic("Field with invalid name");
913 /* check flag consistency */
914 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
915 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
916 panic("Field has invalid access flags");
917 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
918 panic("Field is declared final and volatile");
919 if ((c->flags & ACC_INTERFACE) != 0) {
920 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
921 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
922 panic("Interface field is not declared static final public");
923 if ((f->flags & ACC_TRANSIENT) != 0)
924 panic("Interface field declared transient");
927 /* check descriptor */
928 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
931 f->type = jtype = desc_to_type(f->descriptor); /* data type */
932 f->offset = 0; /* offset from start of object */
937 case TYPE_INT: f->value.i = 0; break;
938 case TYPE_FLOAT: f->value.f = 0.0; break;
939 case TYPE_DOUBLE: f->value.d = 0.0; break;
940 case TYPE_ADDRESS: f->value.a = NULL; break;
943 f->value.l = 0; break;
945 f->value.l.low = 0; f->value.l.high = 0; break;
949 /* read attributes */
950 attrnum = suck_u2(cb);
951 for (i = 0; i < attrnum; i++) {
954 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
956 if (aname != utf_constantvalue) {
957 /* unknown attribute */
958 skipattributebody(cb);
961 /* constant value attribute */
963 if (pindex != field_load_NOVALUE)
964 panic("Field has more than one ConstantValue attribute");
966 /* check attribute length */
967 if (suck_u4(cb) != 2)
968 panic("ConstantValue attribute has invalid length");
970 /* index of value in constantpool */
971 pindex = suck_u2(cb);
973 /* initialize field with value from constantpool */
976 constant_integer *ci =
977 class_getconstant(c, pindex, CONSTANT_Integer);
978 f->value.i = ci->value;
984 class_getconstant(c, pindex, CONSTANT_Long);
985 f->value.l = cl->value;
991 class_getconstant(c, pindex, CONSTANT_Float);
992 f->value.f = cf->value;
997 constant_double *cd =
998 class_getconstant(c, pindex, CONSTANT_Double);
999 f->value.d = cd->value;
1003 case TYPE_ADDRESS: {
1004 utf *u = class_getconstant(c, pindex, CONSTANT_String);
1005 /* create javastring from compressed utf8-string */
1006 f->value.a = literalstring_new(u);
1011 log_text ("Invalid Constant - Type");
1018 /********************** function: field_free **********************************/
1020 static void field_free (fieldinfo *f)
1026 /**************** Function: field_display (debugging only) ********************/
1028 void field_display(fieldinfo *f)
1031 printflags(f->flags);
1033 utf_display(f->name);
1035 utf_display(f->descriptor);
1036 printf(" offset: %ld\n", (long int) (f->offset));
1040 /******************************************************************************/
1041 /************************* Functions for methods ******************************/
1042 /******************************************************************************/
1045 /*********************** Function: method_load *********************************
1047 Loads a method from the class file and fills an existing 'methodinfo'
1048 structure. For native methods, the function pointer field is set to the
1049 real function pointer, for JavaVM methods a pointer to the compiler is used
1052 *******************************************************************************/
1054 static void method_load(classbuffer *cb, classinfo *c, methodinfo *m)
1060 count_all_methods++;
1062 m->thrownexceptionscount=0;
1063 m->linenumbercount=0;
1067 m->flags = suck_u2(cb);
1068 m->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1071 if (!is_valid_name_utf(m->name))
1072 panic("Method with invalid name");
1073 if (m->name->text[0] == '<'
1074 && m->name != utf_init && m->name != utf_clinit)
1075 panic("Method with invalid special name");
1078 m->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1079 argcount = checkmethoddescriptor(m->descriptor);
1080 if ((m->flags & ACC_STATIC) == 0)
1081 argcount++; /* count the 'this' argument */
1085 panic("Method has more than 255 arguments");
1087 /* check flag consistency */
1088 if (m->name != utf_clinit) {
1089 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1090 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1091 panic("Method has invalid access flags");
1092 if ((m->flags & ACC_ABSTRACT) != 0) {
1093 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1094 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1095 panic("Abstract method has invalid flags set");
1097 if ((c->flags & ACC_INTERFACE) != 0) {
1098 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1099 != (ACC_ABSTRACT | ACC_PUBLIC))
1100 panic("Interface method is not declared abstract and public");
1102 if (m->name == utf_init) {
1103 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1104 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1105 panic("Instance initialization method has invalid flags set");
1111 m->exceptiontable = NULL;
1112 m->entrypoint = NULL;
1114 m->stubroutine = NULL;
1115 m->methodUsed = NOTUSED;
1118 m->subRedefsUsed = 0;
1122 if (!(m->flags & ACC_NATIVE)) {
1123 m->stubroutine = createcompilerstub(m);
1126 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1127 (m->flags & ACC_STATIC) != 0);
1129 m->stubroutine = createnativestub(f, m);
1134 attrnum = suck_u2(cb);
1135 for (i = 0; i < attrnum; i++) {
1138 aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1140 if (aname != utf_code) {
1141 if (aname == utf_exceptions) {
1144 suck_u4(cb); /*length*/
1145 exceptionCount=suck_u2(cb);
1146 m->thrownexceptionscount=exceptionCount;
1147 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1148 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1149 (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(cb),CONSTANT_Class);
1153 skipattributebody(cb);
1157 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1158 panic("Code attribute for native or abstract method");
1161 panic("Method has more than one Code attribute");
1164 m->maxstack = suck_u2(cb);
1165 m->maxlocals = suck_u2(cb);
1166 if (m->maxlocals < argcount)
1167 panic("max_locals is smaller than the number of arguments");
1169 codelen = suck_u4(cb);
1172 panic("bytecode has zero length");
1174 if (codelen > 65536)
1175 panic("bytecode too long");
1177 m->jcodelength = codelen;
1178 m->jcode = MNEW(u1, m->jcodelength);
1179 suck_nbytes(m->jcode, cb, m->jcodelength);
1181 m->exceptiontablelength = suck_u2(cb);
1183 MNEW(exceptiontable, m->exceptiontablelength);
1186 count_vmcode_len += m->jcodelength + 18;
1187 count_extable_len += 8 * m->exceptiontablelength;
1190 for (e = 0; e < m->exceptiontablelength; e++) {
1192 m->exceptiontable[e].startpc = suck_u2(cb);
1193 m->exceptiontable[e].endpc = suck_u2(cb);
1194 m->exceptiontable[e].handlerpc = suck_u2(cb);
1198 m->exceptiontable[e].catchtype = NULL;
1201 m->exceptiontable[e].catchtype =
1202 class_getconstant(c, idx, CONSTANT_Class);
1207 for (codeattrnum=suck_u2(cb);codeattrnum>0;codeattrnum--) {
1208 utf * caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1209 if (caname==utf_linenumbertable) {
1211 /*log_text("LineNumberTable found");*/
1213 m->linenumbercount=suck_u2(cb);
1214 /*printf("length:%d\n",m->linenumbercount);*/
1215 m->linenumbers=MNEW(lineinfo,m->linenumbercount);
1216 for (lncid=0;lncid<m->linenumbercount;lncid++) {
1217 m->linenumbers[lncid].start_pc=suck_u2(cb);
1218 m->linenumbers[lncid].line_number=suck_u2(cb);
1221 skipattributes(cb, codeattrnum);
1223 } else skipattributebody(cb);
1230 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1231 panic("Method missing Code attribute");
1235 /********************* Function: method_free ***********************************
1237 frees all memory that was allocated for this method
1239 *******************************************************************************/
1241 static void method_free(methodinfo *m)
1244 MFREE(m->jcode, u1, m->jcodelength);
1246 if (m->exceptiontable)
1247 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1250 CFREE(m->mcode, m->mcodelength);
1252 if (m->stubroutine) {
1253 if (m->flags & ACC_NATIVE) {
1254 removenativestub(m->stubroutine);
1257 removecompilerstub(m->stubroutine);
1263 /************** Function: method_display (debugging only) **************/
1265 void method_display(methodinfo *m)
1268 printflags(m->flags);
1270 utf_display(m->name);
1272 utf_display(m->descriptor);
1276 /************** Function: method_display_flags_last (debugging only) **************/
1278 void method_display_flags_last(methodinfo *m)
1281 utf_display(m->name);
1283 utf_display(m->descriptor);
1285 printflags(m->flags);
1290 /******************** Function: method_canoverwrite ****************************
1292 Check if m and old are identical with respect to type and name. This means
1293 that old can be overwritten with m.
1295 *******************************************************************************/
1297 static bool method_canoverwrite(methodinfo *m, methodinfo *old)
1299 if (m->name != old->name) return false;
1300 if (m->descriptor != old->descriptor) return false;
1301 if (m->flags & ACC_STATIC) return false;
1306 /******************************************************************************/
1307 /************************ Functions for class *********************************/
1308 /******************************************************************************/
1311 /******************** function:: class_getconstant *****************************
1313 retrieves the value at position 'pos' of the constantpool of a class
1314 if the type of the value is other than 'ctype' the system is stopped
1316 *******************************************************************************/
1318 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1320 /* invalid position in constantpool */
1321 /* (pos == 0 is caught by type comparison) */
1322 if (pos >= c->cpcount)
1323 panic("Attempt to access constant outside range");
1325 /* check type of constantpool entry */
1327 if (c->cptags[pos] != ctype) {
1328 class_showconstantpool(c);
1329 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1330 (int) ctype, (int) c->cptags[pos]);
1333 return c->cpinfos[pos];
1337 /********************* Function: class_constanttype ****************************
1339 Determines the type of a class entry in the ConstantPool
1341 *******************************************************************************/
1343 u4 class_constanttype(classinfo *c, u4 pos)
1345 if (pos >= c->cpcount)
1346 panic("Attempt to access constant outside range");
1348 return c->cptags[pos];
1352 /******************** function: class_loadcpool ********************************
1354 loads the constantpool of a class,
1355 the entries are transformed into a simpler format
1356 by resolving references
1357 (a detailed overview of the compact structures can be found in global.h)
1359 *******************************************************************************/
1361 static void class_loadcpool(classbuffer *cb, classinfo *c)
1364 /* The following structures are used to save information which cannot be
1365 processed during the first pass. After the complete constantpool has
1366 been traversed the references can be resolved.
1367 (only in specific order) */
1369 /* CONSTANT_Class_info entries */
1370 typedef struct forward_class {
1371 struct forward_class *next;
1376 /* CONSTANT_String */
1377 typedef struct forward_string {
1378 struct forward_string *next;
1383 /* CONSTANT_NameAndType */
1384 typedef struct forward_nameandtype {
1385 struct forward_nameandtype *next;
1389 } forward_nameandtype;
1391 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1392 typedef struct forward_fieldmethint {
1393 struct forward_fieldmethint *next;
1397 u2 nameandtype_index;
1398 } forward_fieldmethint;
1402 long int dumpsize = dump_size ();
1404 forward_class *forward_classes = NULL;
1405 forward_string *forward_strings = NULL;
1406 forward_nameandtype *forward_nameandtypes = NULL;
1407 forward_fieldmethint *forward_fieldmethints = NULL;
1409 /* number of entries in the constant_pool table plus one */
1410 u4 cpcount = c->cpcount = suck_u2(cb);
1412 /* allocate memory */
1413 u1 *cptags = c->cptags = MNEW(u1, cpcount);
1414 voidptr *cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1417 panic("Invalid constant_pool_count (0)");
1420 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1423 /* initialize constantpool */
1424 for (idx = 0; idx < cpcount; idx++) {
1425 cptags[idx] = CONSTANT_UNUSED;
1426 cpinfos[idx] = NULL;
1430 /******* first pass *******/
1431 /* entries which cannot be resolved now are written into
1432 temporary structures and traversed again later */
1435 while (idx < cpcount) {
1436 /* get constant type */
1440 case CONSTANT_Class: {
1441 forward_class *nfc = DNEW(forward_class);
1443 nfc -> next = forward_classes;
1444 forward_classes = nfc;
1446 nfc -> thisindex = idx;
1447 /* reference to CONSTANT_NameAndType */
1448 nfc -> name_index = suck_u2(cb);
1454 case CONSTANT_Fieldref:
1455 case CONSTANT_Methodref:
1456 case CONSTANT_InterfaceMethodref: {
1457 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1459 nff -> next = forward_fieldmethints;
1460 forward_fieldmethints = nff;
1462 nff -> thisindex = idx;
1465 /* class or interface type that contains the declaration of the field or method */
1466 nff -> class_index = suck_u2(cb);
1467 /* name and descriptor of the field or method */
1468 nff -> nameandtype_index = suck_u2(cb);
1474 case CONSTANT_String: {
1475 forward_string *nfs = DNEW(forward_string);
1477 nfs->next = forward_strings;
1478 forward_strings = nfs;
1480 nfs->thisindex = idx;
1481 /* reference to CONSTANT_Utf8_info with string characters */
1482 nfs->string_index = suck_u2(cb);
1488 case CONSTANT_NameAndType: {
1489 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1491 nfn -> next = forward_nameandtypes;
1492 forward_nameandtypes = nfn;
1494 nfn -> thisindex = idx;
1495 /* reference to CONSTANT_Utf8_info containing simple name */
1496 nfn -> name_index = suck_u2(cb);
1497 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1498 nfn -> sig_index = suck_u2(cb);
1504 case CONSTANT_Integer: {
1505 constant_integer *ci = NEW (constant_integer);
1508 count_const_pool_len += sizeof(constant_integer);
1511 ci -> value = suck_s4(cb);
1512 cptags [idx] = CONSTANT_Integer;
1519 case CONSTANT_Float: {
1520 constant_float *cf = NEW (constant_float);
1523 count_const_pool_len += sizeof(constant_float);
1526 cf -> value = suck_float(cb);
1527 cptags [idx] = CONSTANT_Float;
1533 case CONSTANT_Long: {
1534 constant_long *cl = NEW(constant_long);
1537 count_const_pool_len += sizeof(constant_long);
1540 cl -> value = suck_s8(cb);
1541 cptags [idx] = CONSTANT_Long;
1545 panic("Long constant exceeds constant pool");
1549 case CONSTANT_Double: {
1550 constant_double *cd = NEW(constant_double);
1553 count_const_pool_len += sizeof(constant_double);
1556 cd -> value = suck_double(cb);
1557 cptags [idx] = CONSTANT_Double;
1561 panic("Double constant exceeds constant pool");
1565 case CONSTANT_Utf8: {
1567 /* number of bytes in the bytes array (not string-length) */
1568 u4 length = suck_u2(cb);
1569 cptags [idx] = CONSTANT_Utf8;
1570 /* validate the string */
1571 ASSERT_LEFT(cb, length);
1573 !is_valid_utf(cb->pos + 1, cb->pos + 1 + length))
1575 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1576 panic("Invalid UTF-8 string");
1578 /* insert utf-string into the utf-symboltable */
1579 cpinfos[idx] = utf_new_int(cb->pos + 1, length);
1581 /* skip bytes of the string */
1582 skip_nbytes(cb, length);
1588 error ("Unkown constant type: %d",(int) t);
1596 /* resolve entries in temporary structures */
1598 while (forward_classes) {
1600 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1602 if (opt_verify && !is_valid_name_utf(name))
1603 panic("Class reference with invalid name");
1605 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1606 /* retrieve class from class-table */
1607 cpinfos [forward_classes -> thisindex] = class_new_int (name);
1609 forward_classes = forward_classes -> next;
1613 while (forward_strings) {
1615 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1617 /* resolve utf-string */
1618 cptags [forward_strings -> thisindex] = CONSTANT_String;
1619 cpinfos [forward_strings -> thisindex] = text;
1621 forward_strings = forward_strings -> next;
1624 while (forward_nameandtypes) {
1625 constant_nameandtype *cn = NEW (constant_nameandtype);
1628 count_const_pool_len += sizeof(constant_nameandtype);
1631 /* resolve simple name and descriptor */
1632 cn -> name = class_getconstant
1633 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1634 cn -> descriptor = class_getconstant
1635 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1639 if (!is_valid_name_utf(cn->name))
1640 panic("NameAndType with invalid name");
1641 /* disallow referencing <clinit> among others */
1642 if (cn->name->text[0] == '<' && cn->name != utf_init)
1643 panic("NameAndType with invalid special name");
1646 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1647 cpinfos [forward_nameandtypes -> thisindex] = cn;
1649 forward_nameandtypes = forward_nameandtypes -> next;
1653 while (forward_fieldmethints) {
1654 constant_nameandtype *nat;
1655 constant_FMIref *fmi = NEW(constant_FMIref);
1658 count_const_pool_len += sizeof(constant_FMIref);
1660 /* resolve simple name and descriptor */
1661 nat = class_getconstant(c,
1662 forward_fieldmethints->nameandtype_index,
1663 CONSTANT_NameAndType);
1665 fmi->class = class_getconstant(c,
1666 forward_fieldmethints->class_index,
1668 fmi->name = nat->name;
1669 fmi->descriptor = nat->descriptor;
1671 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1672 cpinfos[forward_fieldmethints->thisindex] = fmi;
1674 switch (forward_fieldmethints->tag) {
1675 case CONSTANT_Fieldref: /* check validity of descriptor */
1676 checkfielddescriptor(fmi->descriptor->text,utf_end(fmi->descriptor));
1678 case CONSTANT_InterfaceMethodref:
1679 case CONSTANT_Methodref: /* check validity of descriptor */
1680 checkmethoddescriptor(fmi->descriptor);
1684 forward_fieldmethints = forward_fieldmethints->next;
1687 /* class_showconstantpool(c); */
1689 dump_release(dumpsize);
1693 /********************** Function: class_load ***********************************
1695 Loads everything interesting about a class from the class file. The
1696 'classinfo' structure must have been allocated previously.
1698 The super class and the interfaces implemented by this class need not be
1699 loaded. The link is set later by the function 'class_link'.
1701 The loaded class is removed from the list 'unloadedclasses' and added to
1702 the list 'unlinkedclasses'.
1704 *******************************************************************************/
1706 classinfo *class_load_intern(classbuffer *cb);
1708 classinfo *class_load(classinfo *c)
1715 #if defined(USE_THREADS)
1716 #if defined(NATIVE_THREADS)
1724 /* maybe the class is already loaded */
1726 #if defined(USE_THREADS)
1727 #if defined(NATIVE_THREADS)
1740 starttime = getcputime();
1742 /* load classdata, throw exception on error */
1744 if ((cb = suck_start(c)) == NULL) {
1745 /* this means, the classpath was not set properly */
1746 if (c->name == utf_java_lang_Object) {
1747 printf("Exception in thread \"main\" java.lang.NoClassDefFoundError: java/lang/Object\n");
1752 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
1755 #if defined(USE_THREADS)
1756 #if defined(NATIVE_THREADS)
1767 /* call the internal function */
1768 r = class_load_intern(cb);
1770 /* if return value is NULL, we had a problem and the class is not loaded */
1778 if (getloadingtime) {
1779 stoptime = getcputime();
1780 loadingtime += (stoptime - starttime);
1783 #if defined(USE_THREADS)
1784 #if defined(NATIVE_THREADS)
1796 classinfo *class_load_intern(classbuffer *cb)
1803 /* get the classbuffer's class */
1806 /* maybe the class is already loaded */
1811 count_class_loads++;
1814 /* output for debugging purposes */
1816 char logtext[MAXLOGTEXT];
1817 sprintf(logtext, "Loading class: ");
1818 utf_sprint_classname(logtext + strlen(logtext), c->name);
1822 /* class is somewhat loaded */
1825 /* check signature */
1826 if (suck_u4(cb) != MAGIC) {
1827 char logtext[MAXLOGTEXT];
1828 utf_sprint_classname(logtext, c->name);
1829 sprintf(logtext + strlen(logtext), " (Bad magic number)");
1832 new_exception_message(string_java_lang_ClassFormatError,
1842 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION + 1 || mi != 0)) {
1843 char logtext[MAXLOGTEXT];
1844 utf_sprint_classname(logtext, c->name);
1845 sprintf(logtext + strlen(logtext),
1846 " (Unsupported major.minor version %d.%d)", ma, mi);
1849 new_exception_message(string_java_lang_ClassFormatError,
1855 class_loadcpool(cb, c);
1857 c->erroneous_state = 0;
1858 c->initializing_thread = 0;
1860 c->classUsed = NOTUSED; /* not used initially CO-RT */
1864 c->flags = suck_u2(cb);
1865 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1867 /* check ACC flags consistency */
1868 if ((c->flags & ACC_INTERFACE) != 0) {
1869 if ((c->flags & ACC_ABSTRACT) == 0) {
1870 /* We work around this because interfaces in JDK 1.1 are
1871 * not declared abstract. */
1873 c->flags |= ACC_ABSTRACT;
1874 /* panic("Interface class not declared abstract"); */
1876 if ((c->flags & (ACC_FINAL)) != 0)
1877 panic("Interface class has invalid flags");
1878 if ((c->flags & (ACC_SUPER)) != 0)
1879 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1881 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1882 panic("Class is declared both abstract and final");
1886 if (class_getconstant(c, i, CONSTANT_Class) != c) {
1887 char message[MAXLOGTEXT];
1888 utf_sprint(message, c->name);
1889 sprintf(message + strlen(message), " (wrong name: ");
1890 utf_sprint(message + strlen(message),
1891 ((classinfo *) class_getconstant(c, i, CONSTANT_Class))->name);
1892 sprintf(message + strlen(message), ")");
1895 new_exception_message(string_java_lang_NoClassDefFoundError,
1901 /* retrieve superclass */
1902 if ((i = suck_u2(cb))) {
1903 c->super = class_getconstant(c, i, CONSTANT_Class);
1905 /* java.lang.Object may not have a super class. */
1906 if (c->name == utf_java_lang_Object)
1907 panic("java.lang.Object with super class");
1909 /* Interfaces must have j.l.O as super class. */
1910 if ((c->flags & ACC_INTERFACE) &&
1911 c->super->name != utf_java_lang_Object) {
1912 panic("Interface with super class other than java.lang.Object");
1918 /* This is only allowed for java.lang.Object. */
1919 if (c->name != utf_java_lang_Object)
1920 panic("Class (not java.lang.Object) without super class");
1923 /* retrieve interfaces */
1924 c->interfacescount = suck_u2(cb);
1925 c->interfaces = MNEW(classinfo*, c->interfacescount);
1926 for (i = 0; i < c->interfacescount; i++) {
1928 class_getconstant(c, suck_u2(cb), CONSTANT_Class);
1932 c->fieldscount = suck_u2(cb);
1934 c->fields = GCNEW(fieldinfo, c->fieldscount);
1935 for (i = 0; i < c->fieldscount; i++) {
1936 field_load(cb, c, &(c->fields[i]));
1940 c->methodscount = suck_u2(cb);
1941 c->methods = MNEW(methodinfo, c->methodscount);
1942 for (i = 0; i < c->methodscount; i++) {
1943 method_load(cb, c, &(c->methods[i]));
1946 /* Check if all fields and methods can be uniquely
1947 * identified by (name,descriptor). */
1949 /* We use a hash table here to avoid making the
1950 * average case quadratic in # of methods, fields.
1952 static int shift = 0;
1954 u2 *next; /* for chaining colliding hash entries */
1960 /* Allocate hashtable */
1961 len = c->methodscount;
1962 if (len < c->fieldscount) len = c->fieldscount;
1964 hashtab = MNEW(u2,(hashlen + len));
1965 next = hashtab + hashlen;
1967 /* Determine bitshift (to get good hash values) */
1977 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
1978 for (i = 0; i < c->fieldscount; ++i) {
1979 fieldinfo *fi = c->fields + i;
1980 /* It's ok if we lose bits here */
1981 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1983 if ((old = hashtab[index]) != 0) {
1985 /* dolog("HASHHIT %d --> %d",index,old); */
1988 /* dolog("HASHCHECK %d",old); */
1989 if (c->fields[old].name == fi->name &&
1990 c->fields[old].descriptor == fi->descriptor) {
1991 dolog("Duplicate field (%d,%d):",i,old);
1992 log_utf(fi->name); log_utf(fi->descriptor);
1993 panic("Fields with same name and descriptor");
1995 } while ((old = next[old]) != 0);
1997 /* else dolog("HASHLUCKY"); */
1998 hashtab[index] = i + 1;
2002 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2003 for (i = 0; i < c->methodscount; ++i) {
2004 methodinfo *mi = c->methods + i;
2005 /* It's ok if we lose bits here */
2006 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
2008 if ((old = hashtab[index]) != 0) {
2010 /* dolog("HASHHIT %d --> %d",index,old); */
2013 /* dolog("HASHCHECK %d",old); */
2014 if (c->methods[old].name == mi->name &&
2015 c->methods[old].descriptor == mi->descriptor) {
2016 dolog("Duplicate method (%d,%d):",i,old);
2017 log_utf(mi->name); log_utf(mi->descriptor);
2018 panic("Methods with same name and descriptor");
2020 } while ((old = next[old]) != 0);
2022 /* else dolog("HASHLUCKY"); */
2023 hashtab[index] = i + 1;
2026 MFREE(hashtab,u2,(hashlen + len));
2030 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2031 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2032 count_class_infos += sizeof(methodinfo) * c->methodscount;
2035 /* load variable-length attribute structures */
2036 attribute_load(cb, c, suck_u2(cb));
2039 /* XXX TWISTI is this still in the JVM spec? SUN and IBM don't complain about it */
2041 /* check if all data has been read */
2042 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2044 if (classdata_left > 0) {
2046 dolog("There are %d extra bytes at end of classfile", classdata_left);
2047 /* The JVM spec disallows extra bytes. */
2048 panic("Extra bytes at end of classfile");
2057 /************** internal Function: class_highestinterface **********************
2059 Used by the function class_link to determine the amount of memory needed
2060 for the interface table.
2062 *******************************************************************************/
2064 static s4 class_highestinterface(classinfo *c)
2069 if (!(c->flags & ACC_INTERFACE)) {
2070 char logtext[MAXLOGTEXT];
2071 sprintf(logtext, "Interface-methods count requested for non-interface: ");
2072 utf_sprint(logtext + strlen(logtext), c->name);
2073 error("%s",logtext);
2077 for (i = 0; i < c->interfacescount; i++) {
2078 s4 h2 = class_highestinterface(c->interfaces[i]);
2086 /* class_addinterface **********************************************************
2088 Is needed by class_link for adding a VTBL to a class. All interfaces
2089 implemented by ic are added as well.
2091 *******************************************************************************/
2093 static void class_addinterface (classinfo *c, classinfo *ic)
2097 vftbl *vftbl = c->vftbl;
2099 if (i >= vftbl->interfacetablelength)
2100 panic ("Inernal error: interfacetable overflow");
2101 if (vftbl->interfacetable[-i])
2104 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
2105 vftbl->interfacevftbllength[i] = 1;
2106 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
2107 vftbl->interfacetable[-i][0] = NULL;
2110 vftbl->interfacevftbllength[i] = ic->methodscount;
2111 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
2114 count_vftbl_len += sizeof(methodptr) *
2115 (ic->methodscount + (ic->methodscount == 0));
2118 for (j=0; j<ic->methodscount; j++) {
2121 for (m = 0; m < sc->methodscount; m++) {
2122 methodinfo *mi = &(sc->methods[m]);
2123 if (method_canoverwrite(mi, &(ic->methods[j]))) {
2124 vftbl->interfacetable[-i][j] =
2125 vftbl->table[mi->vftblindex];
2135 for (j = 0; j < ic->interfacescount; j++)
2136 class_addinterface(c, ic->interfaces[j]);
2140 /******************* Function: class_new_array *********************************
2142 This function is called by class_new to setup an array class.
2144 *******************************************************************************/
2146 void class_new_array(classinfo *c)
2148 classinfo *comp = NULL;
2152 /* Check array class name */
2153 namelen = c->name->blength;
2154 if (namelen < 2 || c->name->text[0] != '[')
2155 panic("Invalid array class name");
2157 /* Check the component type */
2158 switch (c->name->text[1]) {
2160 /* c is an array of arrays. We have to create the component class. */
2161 comp = class_new_int(utf_new_int(c->name->text + 1,namelen - 1));
2165 /* c is an array of objects. */
2166 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2167 panic("Invalid array class name");
2168 comp = class_new_int(utf_new_int(c->name->text + 2,namelen - 3));
2172 /* Setup the array class */
2173 c->super = class_java_lang_Object;
2174 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2176 c->interfacescount = 2;
2177 c->interfaces = MNEW(classinfo*, 2);
2178 c->interfaces[0] = class_new(utf_new_char("java/lang/Cloneable"));
2179 c->interfaces[1] = class_new(utf_new_char("java/io/Serializable"));
2181 c->methodscount = 1;
2182 c->methods = MNEW(methodinfo, c->methodscount);
2185 memset(clone, 0, sizeof(methodinfo));
2186 clone->flags = ACC_PUBLIC;
2187 clone->name = utf_new_char("clone");
2188 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2190 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2191 clone->monoPoly = MONO;
2193 /* XXX: field: length? */
2195 /* array classes are not loaded from class files */
2200 /****************** Function: class_link_array *********************************
2202 This function is called by class_link to create the
2203 arraydescriptor for an array class.
2205 This function returns NULL if the array cannot be linked because
2206 the component type has not been linked yet.
2208 *******************************************************************************/
2210 static arraydescriptor *class_link_array(classinfo *c)
2212 classinfo *comp = NULL;
2213 int namelen = c->name->blength;
2214 arraydescriptor *desc;
2217 /* Check the component type */
2218 switch (c->name->text[1]) {
2220 /* c is an array of arrays. */
2221 comp = class_get(utf_new_int(c->name->text + 1, namelen - 1));
2222 if (!comp) panic("Could not find component array class.");
2226 /* c is an array of objects. */
2227 comp = class_get(utf_new_int(c->name->text + 2, namelen - 3));
2228 if (!comp) panic("Could not find component class.");
2232 /* If the component type has not been linked, link it now */
2233 if (comp && !comp->linked) {
2239 /* Allocate the arraydescriptor */
2240 desc = NEW(arraydescriptor);
2243 /* c is an array of references */
2244 desc->arraytype = ARRAYTYPE_OBJECT;
2245 desc->componentsize = sizeof(void*);
2246 desc->dataoffset = OFFSET(java_objectarray,data);
2248 compvftbl = comp->vftbl;
2250 panic("Component class has no vftbl");
2251 desc->componentvftbl = compvftbl;
2253 if (compvftbl->arraydesc) {
2254 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2255 if (compvftbl->arraydesc->dimension >= 255)
2256 panic("Creating array of dimension >255");
2257 desc->dimension = compvftbl->arraydesc->dimension + 1;
2258 desc->elementtype = compvftbl->arraydesc->elementtype;
2261 desc->elementvftbl = compvftbl;
2262 desc->dimension = 1;
2263 desc->elementtype = ARRAYTYPE_OBJECT;
2267 /* c is an array of a primitive type */
2268 switch (c->name->text[1]) {
2270 desc->arraytype = ARRAYTYPE_BOOLEAN;
2271 desc->dataoffset = OFFSET(java_booleanarray,data);
2272 desc->componentsize = sizeof(u1);
2276 desc->arraytype = ARRAYTYPE_BYTE;
2277 desc->dataoffset = OFFSET(java_bytearray,data);
2278 desc->componentsize = sizeof(u1);
2282 desc->arraytype = ARRAYTYPE_CHAR;
2283 desc->dataoffset = OFFSET(java_chararray,data);
2284 desc->componentsize = sizeof(u2);
2288 desc->arraytype = ARRAYTYPE_DOUBLE;
2289 desc->dataoffset = OFFSET(java_doublearray,data);
2290 desc->componentsize = sizeof(double);
2294 desc->arraytype = ARRAYTYPE_FLOAT;
2295 desc->dataoffset = OFFSET(java_floatarray,data);
2296 desc->componentsize = sizeof(float);
2300 desc->arraytype = ARRAYTYPE_INT;
2301 desc->dataoffset = OFFSET(java_intarray,data);
2302 desc->componentsize = sizeof(s4);
2306 desc->arraytype = ARRAYTYPE_LONG;
2307 desc->dataoffset = OFFSET(java_longarray,data);
2308 desc->componentsize = sizeof(s8);
2312 desc->arraytype = ARRAYTYPE_SHORT;
2313 desc->dataoffset = OFFSET(java_shortarray,data);
2314 desc->componentsize = sizeof(s2);
2318 panic("Invalid array class name");
2321 desc->componentvftbl = NULL;
2322 desc->elementvftbl = NULL;
2323 desc->dimension = 1;
2324 desc->elementtype = desc->arraytype;
2331 /********************** Function: class_link ***********************************
2333 Tries to link a class. The function calculates the length in bytes that
2334 an instance of this class requires as well as the VTBL for methods and
2337 *******************************************************************************/
2339 static classinfo *class_link_intern(classinfo *c);
2341 void class_link(classinfo *c)
2347 #if defined(USE_THREADS)
2348 #if defined(NATIVE_THREADS)
2356 /* maybe the class is already linked */
2358 #if defined(USE_THREADS)
2359 #if defined(NATIVE_THREADS)
2372 starttime = getcputime();
2374 /* call the internal function */
2375 r = class_link_intern(c);
2377 /* if return value is NULL, we had a problem and the class is not linked */
2382 if (getloadingtime) {
2383 stoptime = getcputime();
2384 loadingtime += (stoptime - starttime);
2387 #if defined(USE_THREADS)
2388 #if defined(NATIVE_THREADS)
2398 static classinfo *class_link_intern(classinfo *c)
2400 s4 supervftbllength; /* vftbllegnth of super class */
2401 s4 vftbllength; /* vftbllength of current class */
2402 s4 interfacetablelength; /* interface table length */
2403 classinfo *super = c->super; /* super class */
2404 classinfo *ic, *c2; /* intermediate class variables */
2405 vftbl *v; /* vftbl of current class */
2406 s4 i; /* interface/method/field counter */
2407 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2409 /* maybe the class is already linked */
2414 char logtext[MAXLOGTEXT];
2415 sprintf(logtext, "Linking class: ");
2416 utf_sprint_classname(logtext + strlen(logtext), c->name);
2420 /* ok, this class is somewhat linked */
2423 /* check interfaces */
2425 for (i = 0; i < c->interfacescount; i++) {
2426 ic = c->interfaces[i];
2428 /* detect circularity */
2431 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2443 if (!(ic->flags & ACC_INTERFACE)) {
2444 dolog("Specified interface is not declared as interface:");
2448 panic("Specified interface is not declared as interface");
2452 /* check super class */
2454 if (super == NULL) { /* class java.lang.Object */
2456 c->classUsed = USED; /* Object class is always used CO-RT*/
2458 c->instancesize = sizeof(java_objectheader);
2460 vftbllength = supervftbllength = 0;
2462 c->finalizer = NULL;
2465 /* detect circularity */
2468 new_exception_utfmessage(string_java_lang_ClassCircularityError,
2480 if (super->flags & ACC_INTERFACE)
2481 panic("Interface specified as super class");
2483 /* handle array classes */
2484 /* The component class must have been linked already. */
2485 if (c->name->text[0] == '[') {
2486 if ((arraydesc = class_link_array(c)) == NULL) {
2487 panic("class_link: class_link_array");
2491 /* Don't allow extending final classes */
2492 if (super->flags & ACC_FINAL)
2493 panic("Trying to extend final class");
2495 if (c->flags & ACC_INTERFACE)
2496 c->index = interfaceindex++;
2498 c->index = super->index + 1;
2500 c->instancesize = super->instancesize;
2502 vftbllength = supervftbllength = super->vftbl->vftbllength;
2504 c->finalizer = super->finalizer;
2507 /* compute vftbl length */
2509 for (i = 0; i < c->methodscount; i++) {
2510 methodinfo *m = &(c->methods[i]);
2512 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2513 classinfo *sc = super;
2516 for (j = 0; j < sc->methodscount; j++) {
2517 if (method_canoverwrite(m, &(sc->methods[j]))) {
2518 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2519 goto notfoundvftblindex;
2521 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2524 log_utf(sc->methods[j].name);
2525 log_utf(sc->methods[j].descriptor);
2526 panic("Trying to overwrite final method");
2528 m->vftblindex = sc->methods[j].vftblindex;
2529 goto foundvftblindex;
2535 m->vftblindex = (vftbllength++);
2542 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2545 /* compute interfacetable length */
2547 interfacetablelength = 0;
2550 for (i = 0; i < c2->interfacescount; i++) {
2551 s4 h = class_highestinterface(c2->interfaces[i]) + 1;
2552 if (h > interfacetablelength)
2553 interfacetablelength = h;
2558 /* allocate virtual function table */
2560 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2561 (vftbllength - 1) + sizeof(methodptr*) *
2562 (interfacetablelength - (interfacetablelength > 0)));
2563 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2564 (interfacetablelength > 1));
2565 c->header.vftbl = c->vftbl = v;
2567 v->vftbllength = vftbllength;
2568 v->interfacetablelength = interfacetablelength;
2569 v->arraydesc = arraydesc;
2571 /* store interface index in vftbl */
2572 if (c->flags & ACC_INTERFACE)
2573 v->baseval = -(c->index);
2575 /* copy virtual function table of super class */
2577 for (i = 0; i < supervftbllength; i++)
2578 v->table[i] = super->vftbl->table[i];
2580 /* add method stubs into virtual function table */
2582 for (i = 0; i < c->methodscount; i++) {
2583 methodinfo *m = &(c->methods[i]);
2584 if (!(m->flags & ACC_STATIC)) {
2585 v->table[m->vftblindex] = m->stubroutine;
2589 /* compute instance size and offset of each field */
2591 for (i = 0; i < c->fieldscount; i++) {
2593 fieldinfo *f = &(c->fields[i]);
2595 if (!(f->flags & ACC_STATIC)) {
2596 dsize = desc_typesize(f->descriptor);
2597 c->instancesize = ALIGN(c->instancesize, dsize);
2598 f->offset = c->instancesize;
2599 c->instancesize += dsize;
2603 /* initialize interfacetable and interfacevftbllength */
2605 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2608 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2611 for (i = 0; i < interfacetablelength; i++) {
2612 v->interfacevftbllength[i] = 0;
2613 v->interfacetable[-i] = NULL;
2616 /* add interfaces */
2618 for (c2 = c; c2 != NULL; c2 = c2->super)
2619 for (i = 0; i < c2->interfacescount; i++) {
2620 class_addinterface(c, c2->interfaces[i]);
2623 /* add finalizer method (not for java.lang.Object) */
2625 if (super != NULL) {
2627 static utf *finame = NULL;
2628 static utf *fidesc = NULL;
2631 finame = utf_finalize;
2633 fidesc = utf_fidesc;
2635 fi = class_findmethod(c, finame, fidesc);
2637 if (!(fi->flags & ACC_STATIC)) {
2645 loader_compute_subclasses(c);
2647 /* just return c to show that we don't had a problem */
2653 /******************* Function: class_freepool **********************************
2655 Frees all resources used by this classes Constant Pool.
2657 *******************************************************************************/
2659 static void class_freecpool (classinfo *c)
2665 for (idx=0; idx < c->cpcount; idx++) {
2666 tag = c->cptags[idx];
2667 info = c->cpinfos[idx];
2671 case CONSTANT_Fieldref:
2672 case CONSTANT_Methodref:
2673 case CONSTANT_InterfaceMethodref:
2674 FREE (info, constant_FMIref);
2676 case CONSTANT_Integer:
2677 FREE (info, constant_integer);
2679 case CONSTANT_Float:
2680 FREE (info, constant_float);
2683 FREE (info, constant_long);
2685 case CONSTANT_Double:
2686 FREE (info, constant_double);
2688 case CONSTANT_NameAndType:
2689 FREE (info, constant_nameandtype);
2695 MFREE (c -> cptags, u1, c -> cpcount);
2696 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2700 /*********************** Function: class_free **********************************
2702 Frees all resources used by the class.
2704 *******************************************************************************/
2706 static void class_free(classinfo *c)
2713 MFREE(c->interfaces, classinfo*, c->interfacescount);
2715 for (i = 0; i < c->fieldscount; i++)
2716 field_free(&(c->fields[i]));
2718 for (i = 0; i < c->methodscount; i++)
2719 method_free(&(c->methods[i]));
2720 MFREE(c->methods, methodinfo, c->methodscount);
2722 if ((v = c->vftbl) != NULL) {
2724 mem_free(v->arraydesc,sizeof(arraydescriptor));
2726 for (i = 0; i < v->interfacetablelength; i++) {
2727 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2729 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2731 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2732 sizeof(methodptr*) * (v->interfacetablelength -
2733 (v->interfacetablelength > 0));
2734 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2735 (v->interfacetablelength > 1));
2739 if (c->innerclasscount)
2740 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2742 /* if (c->classvftbl)
2743 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2749 /************************* Function: class_findfield ***************************
2751 Searches a 'classinfo' structure for a field having the given name and
2754 *******************************************************************************/
2756 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2760 for (i = 0; i < c->fieldscount; i++) {
2761 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2762 return &(c->fields[i]);
2765 panic("Can not find field given in CONSTANT_Fieldref");
2767 /* keep compiler happy */
2772 /****************** Function: class_resolvefield_int ***************************
2774 This is an internally used helper function. Do not use this directly.
2776 Tries to resolve a field having the given name and type.
2777 If the field cannot be resolved, NULL is returned.
2779 *******************************************************************************/
2781 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2786 /* search for field in class c */
2787 for (i = 0; i < c->fieldscount; i++) {
2788 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2789 return &(c->fields[i]);
2793 /* try superinterfaces recursively */
2794 for (i = 0; i < c->interfacescount; ++i) {
2795 fi = class_resolvefield_int(c->interfaces[i], name, desc);
2800 /* try superclass */
2802 return class_resolvefield_int(c->super, name, desc);
2809 /********************* Function: class_resolvefield ***************************
2811 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2813 If the field cannot be resolved the return value is NULL. If EXCEPT is
2814 true *exceptionptr is set, too.
2816 *******************************************************************************/
2818 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2819 classinfo *referer, bool except)
2823 /* XXX resolve class c */
2824 /* XXX check access from REFERER to C */
2826 fi = class_resolvefield_int(c, name, desc);
2830 *exceptionptr = new_exception("java/lang/NoSuchFieldError");
2834 /* XXX check access rights */
2840 /************************* Function: class_findmethod **************************
2842 Searches a 'classinfo' structure for a method having the given name and
2843 type and returns the index in the class info structure.
2844 If type is NULL, it is ignored.
2846 *******************************************************************************/
2848 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2852 for (i = 0; i < c->methodscount; i++) {
2853 if ((c->methods[i].name == name) && ((desc == NULL) ||
2854 (c->methods[i].descriptor == desc))) {
2863 /************************* Function: class_findmethod **************************
2865 Searches a 'classinfo' structure for a method having the given name and
2867 If type is NULL, it is ignored.
2869 *******************************************************************************/
2871 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2873 s4 idx = class_findmethodIndex(c, name, desc);
2878 return &(c->methods[idx]);
2882 /*********************** Function: class_fetchmethod **************************
2884 like class_findmethod, but aborts with an error if the method is not found
2886 *******************************************************************************/
2888 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2892 mi = class_findmethod(c, name, desc);
2895 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2896 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2897 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2898 panic("Method not found");
2905 /*********************** Function: class_findmethod_w**************************
2907 like class_findmethod, but logs a warning if the method is not found
2909 *******************************************************************************/
2911 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2914 mi = class_findmethod(c, name, desc);
2917 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2918 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2919 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2921 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2922 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2923 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2924 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2925 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2926 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2927 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2928 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2929 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2930 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2931 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2934 log_plain(" : WARNING: Method not found");log_nl( );
2941 /************************* Function: class_findmethod_approx ******************
2943 like class_findmethod but ignores the return value when comparing the
2946 *******************************************************************************/
2948 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2952 for (i = 0; i < c->methodscount; i++) {
2953 if (c->methods[i].name == name) {
2954 utf *meth_descr = c->methods[i].descriptor;
2958 return &(c->methods[i]);
2960 if (desc->blength <= meth_descr->blength) {
2961 /* current position in utf text */
2962 char *desc_utf_ptr = desc->text;
2963 char *meth_utf_ptr = meth_descr->text;
2964 /* points behind utf strings */
2965 char *desc_end = utf_end(desc);
2966 char *meth_end = utf_end(meth_descr);
2969 /* compare argument types */
2970 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2972 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2973 break; /* no match */
2976 return &(c->methods[i]); /* all parameter types equal */
2986 /***************** Function: class_resolvemethod_approx ***********************
2988 Searches a class and every super class for a method (without paying
2989 attention to the return value)
2991 *******************************************************************************/
2993 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2996 /* search for method (ignore returntype) */
2997 methodinfo *m = class_findmethod_approx(c, name, desc);
3000 /* search superclass */
3008 /************************* Function: class_resolvemethod ***********************
3010 Searches a class and every super class for a method.
3012 *******************************************************************************/
3014 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
3017 methodinfo *m = class_findmethod(c, name, desc);
3019 /* search superclass */
3027 /****************** Function: class_resolveinterfacemethod_int ****************
3029 Internally used helper function. Do not use this directly.
3031 *******************************************************************************/
3034 methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
3039 mi = class_findmethod(c,name,desc);
3043 /* try the superinterfaces */
3044 for (i=0; i<c->interfacescount; ++i) {
3045 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3053 /******************** Function: class_resolveinterfacemethod ******************
3055 Resolves a reference from REFERER to a method with NAME and DESC in
3058 If the method cannot be resolved the return value is NULL. If EXCEPT is
3059 true *exceptionptr is set, too.
3061 *******************************************************************************/
3063 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
3064 classinfo *referer, bool except)
3068 /* XXX resolve class c */
3069 /* XXX check access from REFERER to C */
3071 if ((c->flags & ACC_INTERFACE) == 0) {
3073 *exceptionptr = new_exception("java/lang/IncompatibleClassChangeError");
3077 mi = class_resolveinterfacemethod_int(c, name, desc);
3082 /* try class java.lang.Object */
3083 mi = class_findmethod(class_java_lang_Object,name,desc);
3089 *exceptionptr = new_exception_utfmessage("java/lang/NoSuchMethodError",
3094 /********************* Function: class_resolveclassmethod *********************
3096 Resolves a reference from REFERER to a method with NAME and DESC in
3099 If the method cannot be resolved the return value is NULL. If EXCEPT is
3100 true *exceptionptr is set, too.
3102 *******************************************************************************/
3104 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3105 classinfo *referer, bool except)
3111 /* XXX resolve class c */
3112 /* XXX check access from REFERER to C */
3114 if ((c->flags & ACC_INTERFACE) != 0) {
3117 new_exception("java/lang/IncompatibleClassChangeError");
3121 /* try class c and its superclasses */
3124 mi = class_findmethod(cls, name, desc);
3127 } while ((cls = cls->super) != NULL); /* try the superclass */
3129 /* try the superinterfaces */
3130 for (i = 0; i < c->interfacescount; ++i) {
3131 mi = class_resolveinterfacemethod_int(c->interfaces[i], name, desc);
3137 *exceptionptr = new_exception_utfmessage("java/lang/NoSuchMethodError",
3142 if ((mi->flags & ACC_ABSTRACT) != 0 && (c->flags & ACC_ABSTRACT) == 0) {
3144 *exceptionptr = new_exception("java/lang/AbstractMethodError");
3148 /* XXX check access rights */
3154 /************************* Function: class_issubclass **************************
3156 Checks if sub is a descendant of super.
3158 *******************************************************************************/
3160 bool class_issubclass(classinfo *sub, classinfo *super)
3163 if (!sub) return false;
3164 if (sub == super) return true;
3170 /****************** Initialization function for classes ******************
3172 In Java, every class can have a static initialization function. This
3173 function has to be called BEFORE calling other methods or accessing static
3176 *******************************************************************************/
3178 classinfo *class_init(classinfo *c)
3182 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3186 if (!makeinitializations)
3192 /* class is somewhat initialized */
3193 c->initialized = true;
3203 count_class_inits++;
3206 /* initialize super class */
3208 if (!c->super->loaded)
3209 class_load(c->super);
3211 if (!c->super->linked)
3212 class_link(c->super);
3214 if (!c->super->initialized) {
3216 char logtext[MAXLOGTEXT];
3217 sprintf(logtext, "Initialize super class ");
3218 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3219 sprintf(logtext + strlen(logtext), " from ");
3220 utf_sprint_classname(logtext + strlen(logtext), c->name);
3224 (void) class_init(c->super);
3228 /* initialize interface classes */
3229 for (i = 0; i < c->interfacescount; i++) {
3230 if (!c->interfaces[i]->loaded)
3231 class_load(c->interfaces[i]);
3233 if (!c->interfaces[i]->linked)
3234 class_link(c->interfaces[i]);
3236 if (!c->interfaces[i]->initialized) {
3238 char logtext[MAXLOGTEXT];
3239 sprintf(logtext, "Initialize interface class ");
3240 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3241 sprintf(logtext + strlen(logtext), " from ");
3242 utf_sprint_classname(logtext + strlen(logtext), c->name);
3246 (void) class_init(c->interfaces[i]);
3250 m = class_findmethod(c, utf_clinit, utf_fidesc);
3254 char logtext[MAXLOGTEXT];
3255 sprintf(logtext, "Class ");
3256 utf_sprint_classname(logtext + strlen(logtext), c->name);
3257 sprintf(logtext + strlen(logtext), " has no static class initializer");
3264 if (!(m->flags & ACC_STATIC))
3265 panic("Class initializer is not static!");
3268 char logtext[MAXLOGTEXT];
3269 sprintf(logtext, "Starting static class initializer for class: ");
3270 utf_sprint_classname(logtext + strlen(logtext), c->name);
3274 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3279 /* now call the initializer */
3280 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3282 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3283 assert(blockInts == 0);
3287 /* we have an exception */
3288 if (*exceptionptr) {
3289 java_objectheader *xptr;
3290 java_objectheader *cause;
3292 /* class is NOT initialized */
3293 c->initialized = false;
3296 cause = *exceptionptr;
3298 /* clear exception, because we are calling jit code again */
3299 *exceptionptr = NULL;
3301 /* wrap the exception */
3302 xptr = new_exception_throwable("java/lang/ExceptionInInitializerError",
3303 (java_lang_Throwable *) cause);
3305 if (*exceptionptr) {
3309 /* set new exception */
3310 *exceptionptr = xptr;
3316 char logtext[MAXLOGTEXT];
3317 sprintf(logtext, "Finished static class initializer for class: ");
3318 utf_sprint_classname(logtext + strlen(logtext), c->name);
3326 /********* Function: find_class_method_constant *********/
3328 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3333 for (i=0; i<c->cpcount; i++) {
3335 e = c -> cpinfos [i];
3338 switch (c -> cptags [i]) {
3339 case CONSTANT_Methodref:
3341 constant_FMIref *fmi = e;
3342 if ( (fmi->class->name == c1)
3343 && (fmi->name == m1)
3344 && (fmi->descriptor == d1)) {
3351 case CONSTANT_InterfaceMethodref:
3353 constant_FMIref *fmi = e;
3354 if ( (fmi->class->name == c1)
3355 && (fmi->name == m1)
3356 && (fmi->descriptor == d1)) {
3370 void class_showconstanti(classinfo *c, int ii)
3376 printf ("#%d: ", (int) i);
3378 switch (c->cptags [i]) {
3379 case CONSTANT_Class:
3380 printf("Classreference -> ");
3381 utf_display(((classinfo*)e)->name);
3384 case CONSTANT_Fieldref:
3385 printf("Fieldref -> "); goto displayFMIi;
3386 case CONSTANT_Methodref:
3387 printf("Methodref -> "); goto displayFMIi;
3388 case CONSTANT_InterfaceMethodref:
3389 printf("InterfaceMethod -> "); goto displayFMIi;
3392 constant_FMIref *fmi = e;
3393 utf_display(fmi->class->name);
3395 utf_display(fmi->name);
3397 utf_display(fmi->descriptor);
3401 case CONSTANT_String:
3402 printf("String -> ");
3405 case CONSTANT_Integer:
3406 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3408 case CONSTANT_Float:
3409 printf("Float -> %f", ((constant_float*)e)->value);
3411 case CONSTANT_Double:
3412 printf("Double -> %f", ((constant_double*)e)->value);
3416 u8 v = ((constant_long*)e)->value;
3418 printf("Long -> %ld", (long int) v);
3420 printf("Long -> HI: %ld, LO: %ld\n",
3421 (long int) v.high, (long int) v.low);
3425 case CONSTANT_NameAndType:
3427 constant_nameandtype *cnt = e;
3428 printf("NameAndType: ");
3429 utf_display(cnt->name);
3431 utf_display(cnt->descriptor);
3439 panic("Invalid type of ConstantPool-Entry");
3446 void class_showconstantpool (classinfo *c)
3451 printf ("---- dump of constant pool ----\n");
3453 for (i=0; i<c->cpcount; i++) {
3454 printf ("#%d: ", (int) i);
3456 e = c -> cpinfos [i];
3459 switch (c -> cptags [i]) {
3460 case CONSTANT_Class:
3461 printf ("Classreference -> ");
3462 utf_display ( ((classinfo*)e) -> name );
3465 case CONSTANT_Fieldref:
3466 printf ("Fieldref -> "); goto displayFMI;
3467 case CONSTANT_Methodref:
3468 printf ("Methodref -> "); goto displayFMI;
3469 case CONSTANT_InterfaceMethodref:
3470 printf ("InterfaceMethod -> "); goto displayFMI;
3473 constant_FMIref *fmi = e;
3474 utf_display ( fmi->class->name );
3476 utf_display ( fmi->name);
3478 utf_display ( fmi->descriptor );
3482 case CONSTANT_String:
3483 printf ("String -> ");
3486 case CONSTANT_Integer:
3487 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3489 case CONSTANT_Float:
3490 printf ("Float -> %f", ((constant_float*)e) -> value);
3492 case CONSTANT_Double:
3493 printf ("Double -> %f", ((constant_double*)e) -> value);
3497 u8 v = ((constant_long*)e) -> value;
3499 printf ("Long -> %ld", (long int) v);
3501 printf ("Long -> HI: %ld, LO: %ld\n",
3502 (long int) v.high, (long int) v.low);
3506 case CONSTANT_NameAndType:
3508 constant_nameandtype *cnt = e;
3509 printf ("NameAndType: ");
3510 utf_display (cnt->name);
3512 utf_display (cnt->descriptor);
3516 printf ("Utf8 -> ");
3520 panic ("Invalid type of ConstantPool-Entry");
3530 /********** Function: class_showmethods (debugging only) *************/
3532 void class_showmethods (classinfo *c)
3536 printf ("--------- Fields and Methods ----------------\n");
3537 printf ("Flags: "); printflags (c->flags); printf ("\n");
3539 printf ("This: "); utf_display (c->name); printf ("\n");
3541 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3543 printf ("Index: %d\n", c->index);
3545 printf ("interfaces:\n");
3546 for (i=0; i < c-> interfacescount; i++) {
3548 utf_display (c -> interfaces[i] -> name);
3549 printf (" (%d)\n", c->interfaces[i] -> index);
3552 printf ("fields:\n");
3553 for (i=0; i < c -> fieldscount; i++) {
3554 field_display (&(c -> fields[i]));
3557 printf ("methods:\n");
3558 for (i=0; i < c -> methodscount; i++) {
3559 methodinfo *m = &(c->methods[i]);
3560 if ( !(m->flags & ACC_STATIC))
3561 printf ("vftblindex: %d ", m->vftblindex);
3563 method_display ( m );
3567 printf ("Virtual function table:\n");
3568 for (i=0; i<c->vftbl->vftbllength; i++) {
3569 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3575 /******************************************************************************/
3576 /******************* General functions for the class loader *******************/
3577 /******************************************************************************/
3579 /**************** function: create_primitive_classes ***************************
3581 create classes representing primitive types
3583 *******************************************************************************/
3585 void create_primitive_classes()
3589 for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
3590 /* create primitive class */
3591 classinfo *c = class_new_int(utf_new_char(primitivetype_table[i].name));
3592 c->classUsed = NOTUSED; /* not used initially CO-RT */
3595 /* prevent loader from loading primitive class */
3599 primitivetype_table[i].class_primitive = c;
3601 /* create class for wrapping the primitive type */
3602 c = class_new_int(utf_new_char(primitivetype_table[i].wrapname));
3603 primitivetype_table[i].class_wrap = c;
3604 primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
3605 primitivetype_table[i].class_wrap->impldBy = NULL;
3607 /* create the primitive array class */
3608 if (primitivetype_table[i].arrayname) {
3609 c = class_new_int(utf_new_char(primitivetype_table[i].arrayname));
3610 primitivetype_table[i].arrayclass = c;
3614 primitivetype_table[i].arrayvftbl = c->vftbl;
3620 /**************** function: class_primitive_from_sig ***************************
3622 return the primitive class indicated by the given signature character
3624 If the descriptor does not indicate a valid primitive type the
3625 return value is NULL.
3627 ********************************************************************************/
3629 classinfo *class_primitive_from_sig(char sig)
3632 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3633 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3634 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3635 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3636 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3637 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3638 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3639 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3640 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3645 /****************** function: class_from_descriptor ****************************
3647 return the class indicated by the given descriptor
3649 utf_ptr....first character of descriptor
3650 end_ptr....first character after the end of the string
3651 next.......if non-NULL, *next is set to the first character after
3652 the descriptor. (Undefined if an error occurs.)
3654 mode.......a combination (binary or) of the following flags:
3656 (Flags marked with * are the default settings.)
3658 What to do if a reference type descriptor is parsed successfully:
3660 CLASSLOAD_SKIP...skip it and return something != NULL
3661 * CLASSLOAD_NEW....get classinfo * via class_new
3662 CLASSLOAD_LOAD...get classinfo * via loader_load
3664 How to handle primitive types:
3666 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3667 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3669 How to handle "V" descriptors:
3671 * CLASSLOAD_VOID.....handle it like other primitive types
3672 CLASSLOAD_NOVOID...treat it as an error
3674 How to deal with extra characters after the end of the
3677 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3678 CLASSLOAD_CHECKEND.....treat them as an error
3680 How to deal with errors:
3682 * CLASSLOAD_PANIC....abort execution with an error message
3683 CLASSLOAD_NOPANIC..return NULL on error
3685 ********************************************************************************/
3687 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3688 char **next, int mode)
3690 char *start = utf_ptr;
3694 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3696 if (mode & CLASSLOAD_CHECKEND)
3697 error |= (utf_ptr != end_ptr);
3700 if (next) *next = utf_ptr;
3704 if (mode & CLASSLOAD_NOVOID)
3715 return (mode & CLASSLOAD_NULLPRIMITIVE)
3717 : class_primitive_from_sig(*start);
3724 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3725 name = utf_new(start, utf_ptr - start);
3726 return (mode & CLASSLOAD_LOAD)
3727 ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
3731 /* An error occurred */
3732 if (mode & CLASSLOAD_NOPANIC)
3735 log_plain("Invalid descriptor at beginning of '");
3736 log_plain_utf(utf_new(start, end_ptr - start));
3740 panic("Invalid descriptor");
3742 /* keep compiler happy */
3747 /******************* function: type_from_descriptor ****************************
3749 return the basic type indicated by the given descriptor
3751 This function parses a descriptor and returns its basic type as
3752 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3754 cls...if non-NULL the referenced variable is set to the classinfo *
3755 returned by class_from_descriptor.
3757 For documentation of the arguments utf_ptr, end_ptr, next and mode
3758 see class_from_descriptor. The only difference is that
3759 type_from_descriptor always uses CLASSLOAD_PANIC.
3761 ********************************************************************************/
3763 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3764 char **next, int mode)
3767 if (!cls) cls = &mycls;
3768 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3785 return TYPE_ADDRESS;
3789 /*************** function: create_pseudo_classes *******************************
3791 create pseudo classes used by the typechecker
3793 ********************************************************************************/
3795 static void create_pseudo_classes()
3797 /* pseudo class for Arraystubs (extends java.lang.Object) */
3799 pseudo_class_Arraystub = class_new_int(utf_new_char("$ARRAYSTUB$"));
3800 /* list_remove(&unloadedclasses, pseudo_class_Arraystub); */
3801 pseudo_class_Arraystub->loaded = true;
3803 pseudo_class_Arraystub->super = class_java_lang_Object;
3804 pseudo_class_Arraystub->interfacescount = 2;
3805 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3806 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3807 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3809 /* list_addlast(&unlinkedclasses, pseudo_class_Arraystub); */
3810 class_link(pseudo_class_Arraystub);
3812 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3814 /* pseudo class representing the null type */
3816 pseudo_class_Null = class_new_int(utf_new_char("$NULL$"));
3817 /* list_remove(&unloadedclasses, pseudo_class_Null); */
3818 pseudo_class_Null->loaded = true;
3820 pseudo_class_Null->super = class_java_lang_Object;
3822 /* list_addlast(&unlinkedclasses, pseudo_class_Null); */
3823 class_link(pseudo_class_Null);
3825 /* pseudo class representing new uninitialized objects */
3827 pseudo_class_New = class_new_int(utf_new_char("$NEW$"));
3828 /* list_remove(&unloadedclasses, pseudo_class_New); */
3829 pseudo_class_New->linked = true;
3831 pseudo_class_New->super = class_java_lang_Object;
3833 /* list_addlast(&unlinkedclasses, pseudo_class_New); */
3834 class_link(pseudo_class_New);
3838 /********************** Function: loader_init **********************************
3840 Initializes all lists and loads all classes required for the system or the
3843 *******************************************************************************/
3845 void loader_init(u1 *stackbottom)
3849 /* create utf-symbols for pointer comparison of frequently used strings */
3850 utf_innerclasses = utf_new_char("InnerClasses");
3851 utf_constantvalue = utf_new_char("ConstantValue");
3852 utf_code = utf_new_char("Code");
3853 utf_exceptions = utf_new_char("Exceptions");
3854 utf_linenumbertable = utf_new_char("LineNumberTable");
3855 utf_sourcefile = utf_new_char("SourceFile");
3856 utf_finalize = utf_new_char("finalize");
3857 utf_fidesc = utf_new_char("()V");
3858 utf_init = utf_new_char("<init>");
3859 utf_clinit = utf_new_char("<clinit>");
3860 utf_initsystemclass = utf_new_char("initializeSystemClass");
3861 utf_systemclass = utf_new_char("java/lang/System");
3862 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3863 utf_initialize = utf_new_char("initialize");
3864 utf_initializedesc = utf_new_char("(I)V");
3866 utf_vmclass = utf_new_char("java/lang/VMClass");
3867 utf_java_lang_Object= utf_new_char("java/lang/Object");
3869 array_packagename = utf_new_char("<the array package>");
3871 /* create some important classes */
3872 /* These classes have to be created now because the classinfo
3873 * pointers are used in the loading code.
3875 class_java_lang_Object =
3876 class_new_int(utf_java_lang_Object);
3877 class_load(class_java_lang_Object);
3878 class_link(class_java_lang_Object);
3880 class_java_lang_String =
3881 class_new_int(utf_new_char("java/lang/String"));
3882 class_load(class_java_lang_String);
3883 class_link(class_java_lang_String);
3885 class_java_lang_Cloneable =
3886 class_new_int(utf_new_char("java/lang/Cloneable"));
3887 class_load(class_java_lang_Cloneable);
3888 class_link(class_java_lang_Cloneable);
3890 class_java_io_Serializable =
3891 class_new_int(utf_new_char("java/io/Serializable"));
3892 class_load(class_java_io_Serializable);
3893 class_link(class_java_io_Serializable);
3895 class_java_lang_Throwable =
3896 class_new(utf_new_char("java/lang/Throwable"));
3897 class_load(class_java_lang_Throwable);
3898 class_link(class_java_lang_Throwable);
3900 /* create classes representing primitive types */
3901 create_primitive_classes();
3903 /* create classes used by the typechecker */
3904 create_pseudo_classes();
3906 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3907 stringtable_update();
3909 #if defined(USE_THREADS)
3910 if (stackbottom != 0)
3916 static void loader_compute_class_values(classinfo *c)
3920 c->vftbl->baseval = ++classvalue;
3923 while (subs != NULL) {
3924 loader_compute_class_values(subs);
3925 subs = subs->nextsub;
3928 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3932 void loader_compute_subclasses(classinfo *c)
3934 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3938 if (!(c->flags & ACC_INTERFACE)) {
3943 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3944 c->nextsub = c->super->sub;
3950 /* this is the java.lang.Object special case */
3951 if (!class_java_lang_Object) {
3952 loader_compute_class_values(c);
3955 loader_compute_class_values(class_java_lang_Object);
3958 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3964 /******************** Function: loader_close ***********************************
3968 *******************************************************************************/
3974 /* while ((c = list_first(&unloadedclasses))) { */
3975 /* list_remove(&unloadedclasses, c); */
3976 /* class_free(c); */
3978 /* while ((c = list_first(&unlinkedclasses))) { */
3979 /* list_remove(&unlinkedclasses, c); */
3980 /* class_free(c); */
3982 /* while ((c = list_first(&linkedclasses))) { */
3983 /* list_remove(&linkedclasses, c); */
3984 /* class_free(c); */
3990 * These are local overrides for various environment variables in Emacs.
3991 * Please do not remove this and leave it at the end of the file, where
3992 * Emacs will automagically detect them.
3993 * ---------------------------------------------------------------------
3996 * indent-tabs-mode: t