1 /* src/vm/loader.c - class loader functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
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
29 Changes: Andreas Krall
35 $Id: loader.c 2193 2005-04-02 19:33:43Z edwin $
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "native/include/java_lang_Throwable.h"
50 #if defined(USE_THREADS)
51 # if defined(NATIVE_THREADS)
52 # include "threads/native/threads.h"
54 # include "threads/green/threads.h"
55 # include "threads/green/locks.h"
59 #include "toolbox/logging.h"
60 #include "toolbox/util.h"
61 #include "vm/exceptions.h"
62 #include "vm/builtin.h"
63 #include "vm/global.h"
64 #include "vm/linker.h"
65 #include "vm/loader.h"
66 #include "vm/options.h"
67 #include "vm/statistics.h"
68 #include "vm/stringlocal.h"
69 #include "vm/tables.h"
70 #include "vm/classcache.h"
73 # include "vm/unzip.h"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/codegen.inc.h"
80 /******************************************************************************/
82 /******************************************************************************/
84 /*#define LOADER_VERBOSE*/
91 #define LOADER_ASSERT(cond) assert(cond)
93 #define LOADER_ASSERT(cond)
101 /********************************************************************
102 list of classpath entries (either filesystem directories or
104 ********************************************************************/
106 classpath_info *classpath_entries = NULL;
108 /* loader_init *****************************************************************
110 Initializes all lists and loads all classes required for the system
113 *******************************************************************************/
115 bool loader_init(u1 *stackbottom)
119 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
120 /* Initialize the monitor pointer for zip/jar file locking. */
122 for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
123 if (cpi->type == CLASSPATH_ARCHIVE)
124 initObjectLock(&cpi->header);
128 /* load some important classes */
130 if (!load_class_bootstrap(utf_java_lang_Object,&class_java_lang_Object))
133 if (!load_class_bootstrap(utf_java_lang_String,&class_java_lang_String))
136 if (!load_class_bootstrap(utf_java_lang_Cloneable,&class_java_lang_Cloneable))
139 if (!load_class_bootstrap(utf_java_io_Serializable,&class_java_io_Serializable))
143 /* load classes for wrapping primitive types */
145 if (!load_class_bootstrap(utf_java_lang_Void,&class_java_lang_Void))
148 if (!load_class_bootstrap(utf_java_lang_Boolean,&class_java_lang_Boolean))
151 if (!load_class_bootstrap(utf_java_lang_Byte,&class_java_lang_Byte))
154 if (!load_class_bootstrap(utf_java_lang_Character,&class_java_lang_Character))
157 if (!load_class_bootstrap(utf_java_lang_Short,&class_java_lang_Short))
160 if (!load_class_bootstrap(utf_java_lang_Integer,&class_java_lang_Integer))
163 if (!load_class_bootstrap(utf_java_lang_Long,&class_java_lang_Long))
166 if (!load_class_bootstrap(utf_java_lang_Float,&class_java_lang_Float))
169 if (!load_class_bootstrap(utf_java_lang_Double,&class_java_lang_Double))
172 /* load some other important classes */
174 if (!load_class_bootstrap(utf_java_lang_Class,&class_java_lang_Class))
177 if (!load_class_bootstrap(utf_java_lang_ClassLoader,&class_java_lang_ClassLoader))
180 if (!load_class_bootstrap(utf_java_lang_SecurityManager,&class_java_lang_SecurityManager))
183 if (!load_class_bootstrap(utf_java_lang_System,&class_java_lang_System))
186 if (!load_class_bootstrap(utf_java_lang_Throwable,&class_java_lang_Throwable))
189 if (!load_class_bootstrap(utf_java_lang_VMThrowable,&class_java_lang_VMThrowable))
192 if (!load_class_bootstrap(utf_java_lang_Exception,&class_java_lang_Exception))
195 if (!load_class_bootstrap(utf_java_lang_Error,&class_java_lang_Error))
198 if (!load_class_bootstrap(utf_java_lang_OutOfMemoryError,&class_java_lang_OutOfMemoryError))
201 if (!load_class_bootstrap(utf_java_lang_NoClassDefFoundError,&class_java_lang_NoClassDefFoundError))
204 if (!load_class_bootstrap(utf_java_util_Vector,&class_java_util_Vector))
207 #if defined(USE_THREADS)
208 if (stackbottom != 0)
216 /************* functions for reading classdata *********************************
218 getting classdata in blocks of variable size
219 (8,16,32,64-bit integer or float)
221 *******************************************************************************/
223 /* check_classbuffer_size ******************************************************
225 assert that at least <len> bytes are left to read
226 <len> is limited to the range of non-negative s4 values
228 *******************************************************************************/
230 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
232 if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
234 new_classformaterror((cb)->class, "Truncated class file");
243 /* suck_nbytes *****************************************************************
245 transfer block of classfile data into a buffer
247 *******************************************************************************/
249 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
251 memcpy(buffer, cb->pos + 1, len);
256 /* skip_nbytes ****************************************************************
258 skip block of classfile data
260 *******************************************************************************/
262 inline void skip_nbytes(classbuffer *cb, s4 len)
268 inline u1 suck_u1(classbuffer *cb)
274 inline u2 suck_u2(classbuffer *cb)
278 return ((u2) a << 8) + (u2) b;
282 inline u4 suck_u4(classbuffer *cb)
288 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
292 /* get u8 from classfile data */
293 static u8 suck_u8(classbuffer *cb)
299 return (hi << 32) + lo;
302 v.high = suck_u4(cb);
309 /* get float from classfile data */
310 static float suck_float(classbuffer *cb)
318 for (i = 0; i < 4; i++)
319 buffer[3 - i] = suck_u1(cb);
321 memcpy((u1*) (&f), buffer, 4);
323 suck_nbytes((u1*) (&f), cb, 4);
326 if (sizeof(float) != 4) {
327 *exceptionptr = new_exception_message(string_java_lang_InternalError,
328 "Incompatible float-format");
330 /* XXX should we exit in such a case? */
331 throw_exception_exit();
338 /* get double from classfile data */
339 static double suck_double(classbuffer *cb)
347 for (i = 0; i < 8; i++)
348 buffer[7 - i] = suck_u1(cb);
350 memcpy((u1*) (&d), buffer, 8);
352 suck_nbytes((u1*) (&d), cb, 8);
355 if (sizeof(double) != 8) {
356 *exceptionptr = new_exception_message(string_java_lang_InternalError,
357 "Incompatible double-format");
359 /* XXX should we exit in such a case? */
360 throw_exception_exit();
367 /************************** function suck_init *********************************
369 called once at startup, sets the searchpath for the classfiles
371 *******************************************************************************/
373 void suck_init(char *classpath)
381 classpath_info *lastcpi;
385 /* search for last classpath entry (only if there already some) */
387 if ((lastcpi = classpath_entries)) {
388 while (lastcpi->next)
389 lastcpi = lastcpi->next;
392 for (start = classpath; (*start) != '\0';) {
394 /* search for ':' delimiter to get the end of the current entry */
395 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
399 filenamelen = end - start;
401 if (filenamelen > 3) {
402 if (strncasecmp(end - 3, "zip", 3) == 0 ||
403 strncasecmp(end - 3, "jar", 3) == 0) {
408 /* save classpath entries as absolute pathnames */
413 if (*start != '/') { /* XXX fix me for win32 */
415 cwdlen = strlen(cwd) + strlen("/");
418 /* allocate memory for filename and fill it */
420 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
424 strcpy(filename, cwd);
425 strcat(filename, "/");
426 strncat(filename, start, filenamelen);
428 /* add cwd length to file length */
429 filenamelen += cwdlen;
432 strncpy(filename, start, filenamelen);
433 filename[filenamelen] = '\0';
439 #if defined(USE_ZLIB)
440 unzFile uf = unzOpen(filename);
443 cpi = NEW(classpath_info);
444 cpi->type = CLASSPATH_ARCHIVE;
447 cpi->path = filename;
448 cpi->pathlen = filenamelen;
452 throw_cacao_exception_exit(string_java_lang_InternalError,
453 "zip/jar files not supported");
457 cpi = NEW(classpath_info);
458 cpi->type = CLASSPATH_PATH;
461 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
462 filename[filenamelen] = '/';
463 filename[filenamelen + 1] = '\0';
467 cpi->path = filename;
468 cpi->pathlen = filenamelen;
471 /* attach current classpath entry */
474 if (!classpath_entries)
475 classpath_entries = cpi;
483 /* goto next classpath entry, skip ':' delimiter */
495 void create_all_classes()
499 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
500 #if defined(USE_ZLIB)
501 if (cpi->type == CLASSPATH_ARCHIVE) {
505 s = (unz_s *) cpi->uf;
506 ce = s->cacao_dir_list;
509 (void) class_new(ce->name);
515 #if defined(USE_ZLIB)
522 /* suck_start ******************************************************************
524 Returns true if classbuffer is already loaded or a file for the
525 specified class has succussfully been read in. All directories of
526 the searchpath are used to find the classfile (<classname>.class).
527 Returns false if no classfile is found and writes an error message.
529 *******************************************************************************/
531 classbuffer *suck_start(classinfo *c)
543 /* initialize return value */
548 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
549 filename = MNEW(char, filenamelen);
551 utf_sprint(filename, c->name);
552 strcat(filename, ".class");
554 /* walk through all classpath entries */
556 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
557 #if defined(USE_ZLIB)
558 if (cpi->type == CLASSPATH_ARCHIVE) {
560 #if defined(USE_THREADS)
561 /* enter a monitor on zip/jar archives */
563 builtin_monitorenter((java_objectheader *) cpi);
566 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
567 unz_file_info file_info;
569 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
570 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
571 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
572 cb = NEW(classbuffer);
574 cb->size = file_info.uncompressed_size;
575 cb->data = MNEW(u1, cb->size);
576 cb->pos = cb->data - 1;
578 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
580 if (len != cb->size) {
582 log_text("Error while unzipping");
589 log_text("Error while opening file in archive");
593 log_text("Error while retrieving fileinfo");
596 unzCloseCurrentFile(cpi->uf);
598 #if defined(USE_THREADS)
599 /* leave the monitor */
601 builtin_monitorexit((java_objectheader *) cpi);
605 #endif /* defined(USE_ZLIB) */
607 path = MNEW(char, cpi->pathlen + filenamelen);
608 strcpy(path, cpi->path);
609 strcat(path, filename);
611 classfile = fopen(path, "r");
613 if (classfile) { /* file exists */
614 if (!stat(path, &buffer)) { /* read classfile data */
615 cb = NEW(classbuffer);
617 cb->size = buffer.st_size;
618 cb->data = MNEW(u1, cb->size);
619 cb->pos = cb->data - 1;
621 /* read class data */
622 len = fread(cb->data, 1, cb->size, classfile);
624 if (len != buffer.st_size) {
626 /* if (ferror(classfile)) { */
635 MFREE(path, char, cpi->pathlen + filenamelen);
636 #if defined(USE_ZLIB)
643 dolog("Warning: Can not open class file '%s'", filename);
645 MFREE(filename, char, filenamelen);
651 /************************** function suck_stop *********************************
653 frees memory for buffer with classfile data.
654 Caution: this function may only be called if buffer has been allocated
655 by suck_start with reading a file
657 *******************************************************************************/
659 void suck_stop(classbuffer *cb)
663 MFREE(cb->data, u1, cb->size);
664 FREE(cb, classbuffer);
668 /******************************************************************************/
669 /******************* Some support functions ***********************************/
670 /******************************************************************************/
672 void fprintflags (FILE *fp, u2 f)
674 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
675 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
676 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
677 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
678 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
679 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
680 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
681 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
682 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
683 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
684 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
688 /********** internal function: printflags (only for debugging) ***************/
690 void printflags(u2 f)
692 fprintflags(stdout,f);
696 /********************** Function: skipattributebody ****************************
698 skips an attribute after the 16 bit reference to attribute_name has already
701 *******************************************************************************/
703 static bool skipattributebody(classbuffer *cb)
707 if (!check_classbuffer_size(cb, 4))
712 if (!check_classbuffer_size(cb, len))
715 skip_nbytes(cb, len);
721 /************************* Function: skipattributes ****************************
723 skips num attribute structures
725 *******************************************************************************/
727 static bool skipattributes(classbuffer *cb, u4 num)
732 for (i = 0; i < num; i++) {
733 if (!check_classbuffer_size(cb, 2 + 4))
739 if (!check_classbuffer_size(cb, len))
742 skip_nbytes(cb, len);
749 /******************** function:: class_getconstant *****************************
751 retrieves the value at position 'pos' of the constantpool of a class
752 if the type of the value is other than 'ctype' the system is stopped
754 *******************************************************************************/
756 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
758 /* check index and type of constantpool entry */
759 /* (pos == 0 is caught by type comparison) */
760 if (pos >= c->cpcount || c->cptags[pos] != ctype) {
761 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
765 return c->cpinfos[pos];
769 /******************** function: innerclass_getconstant ************************
771 like class_getconstant, but if cptags is ZERO null is returned
773 *******************************************************************************/
775 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
777 /* invalid position in constantpool */
778 if (pos >= c->cpcount) {
779 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
783 /* constantpool entry of type 0 */
787 /* check type of constantpool entry */
788 if (c->cptags[pos] != ctype) {
789 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
793 return c->cpinfos[pos];
797 /********************* Function: class_constanttype ****************************
799 Determines the type of a class entry in the ConstantPool
801 *******************************************************************************/
803 u4 class_constanttype(classinfo *c, u4 pos)
805 if (pos <= 0 || pos >= c->cpcount) {
806 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
810 return c->cptags[pos];
814 /* load_constantpool ***********************************************************
816 Loads the constantpool of a class, the entries are transformed into
817 a simpler format by resolving references (a detailed overview of
818 the compact structures can be found in global.h).
820 *******************************************************************************/
822 static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
825 /* The following structures are used to save information which cannot be
826 processed during the first pass. After the complete constantpool has
827 been traversed the references can be resolved.
828 (only in specific order) */
830 /* CONSTANT_Class entries */
831 typedef struct forward_class {
832 struct forward_class *next;
837 /* CONSTANT_String */
838 typedef struct forward_string {
839 struct forward_string *next;
844 /* CONSTANT_NameAndType */
845 typedef struct forward_nameandtype {
846 struct forward_nameandtype *next;
850 } forward_nameandtype;
852 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
853 typedef struct forward_fieldmethint {
854 struct forward_fieldmethint *next;
858 u2 nameandtype_index;
859 } forward_fieldmethint;
865 forward_class *forward_classes = NULL;
866 forward_string *forward_strings = NULL;
867 forward_nameandtype *forward_nameandtypes = NULL;
868 forward_fieldmethint *forward_fieldmethints = NULL;
872 forward_nameandtype *nfn;
873 forward_fieldmethint *nff;
881 /* number of entries in the constant_pool table plus one */
882 if (!check_classbuffer_size(cb, 2))
885 cpcount = c->cpcount = suck_u2(cb);
887 /* allocate memory */
888 cptags = c->cptags = MNEW(u1, cpcount);
889 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
892 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
896 #if defined(STATISTICS)
898 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
901 /* initialize constantpool */
902 for (idx = 0; idx < cpcount; idx++) {
903 cptags[idx] = CONSTANT_UNUSED;
908 /******* first pass *******/
909 /* entries which cannot be resolved now are written into
910 temporary structures and traversed again later */
913 while (idx < cpcount) {
916 /* get constant type */
917 if (!check_classbuffer_size(cb, 1))
924 nfc = DNEW(forward_class);
926 nfc->next = forward_classes;
927 forward_classes = nfc;
929 nfc->thisindex = idx;
930 /* reference to CONSTANT_NameAndType */
931 if (!check_classbuffer_size(cb, 2))
934 nfc->name_index = suck_u2(cb);
939 case CONSTANT_String:
940 nfs = DNEW(forward_string);
942 nfs->next = forward_strings;
943 forward_strings = nfs;
945 nfs->thisindex = idx;
947 /* reference to CONSTANT_Utf8_info with string characters */
948 if (!check_classbuffer_size(cb, 2))
951 nfs->string_index = suck_u2(cb);
956 case CONSTANT_NameAndType:
957 nfn = DNEW(forward_nameandtype);
959 nfn->next = forward_nameandtypes;
960 forward_nameandtypes = nfn;
962 nfn->thisindex = idx;
964 if (!check_classbuffer_size(cb, 2 + 2))
967 /* reference to CONSTANT_Utf8_info containing simple name */
968 nfn->name_index = suck_u2(cb);
970 /* reference to CONSTANT_Utf8_info containing field or method
972 nfn->sig_index = suck_u2(cb);
977 case CONSTANT_Fieldref:
978 case CONSTANT_Methodref:
979 case CONSTANT_InterfaceMethodref:
980 nff = DNEW(forward_fieldmethint);
982 nff->next = forward_fieldmethints;
983 forward_fieldmethints = nff;
985 nff->thisindex = idx;
989 if (!check_classbuffer_size(cb, 2 + 2))
992 /* class or interface type that contains the declaration of the
994 nff->class_index = suck_u2(cb);
996 /* name and descriptor of the field or method */
997 nff->nameandtype_index = suck_u2(cb);
1002 case CONSTANT_Integer: {
1003 constant_integer *ci = NEW(constant_integer);
1005 #if defined(STATISTICS)
1007 count_const_pool_len += sizeof(constant_integer);
1010 if (!check_classbuffer_size(cb, 4))
1013 ci->value = suck_s4(cb);
1014 cptags[idx] = CONSTANT_Integer;
1021 case CONSTANT_Float: {
1022 constant_float *cf = NEW(constant_float);
1024 #if defined(STATISTICS)
1026 count_const_pool_len += sizeof(constant_float);
1029 if (!check_classbuffer_size(cb, 4))
1032 cf->value = suck_float(cb);
1033 cptags[idx] = CONSTANT_Float;
1040 case CONSTANT_Long: {
1041 constant_long *cl = NEW(constant_long);
1043 #if defined(STATISTICS)
1045 count_const_pool_len += sizeof(constant_long);
1048 if (!check_classbuffer_size(cb, 8))
1051 cl->value = suck_s8(cb);
1052 cptags[idx] = CONSTANT_Long;
1055 if (idx > cpcount) {
1057 new_classformaterror(c, "Invalid constant pool entry");
1063 case CONSTANT_Double: {
1064 constant_double *cd = NEW(constant_double);
1066 #if defined(STATISTICS)
1068 count_const_pool_len += sizeof(constant_double);
1071 if (!check_classbuffer_size(cb, 8))
1074 cd->value = suck_double(cb);
1075 cptags[idx] = CONSTANT_Double;
1078 if (idx > cpcount) {
1080 new_classformaterror(c, "Invalid constant pool entry");
1086 case CONSTANT_Utf8: {
1089 /* number of bytes in the bytes array (not string-length) */
1090 if (!check_classbuffer_size(cb, 2))
1093 length = suck_u2(cb);
1094 cptags[idx] = CONSTANT_Utf8;
1096 /* validate the string */
1097 if (!check_classbuffer_size(cb, length))
1101 !is_valid_utf((char *) (cb->pos + 1),
1102 (char *) (cb->pos + 1 + length))) {
1103 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1104 panic("Invalid UTF-8 string");
1106 /* insert utf-string into the utf-symboltable */
1107 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1109 /* skip bytes of the string (buffer size check above) */
1110 skip_nbytes(cb, length);
1117 new_classformaterror(c, "Illegal constant pool type");
1122 /* add all class references to the descriptor_pool */
1123 for (nfc=forward_classes; nfc; nfc=nfc->next) {
1124 utf *name = class_getconstant(c,nfc->name_index,CONSTANT_Utf8);
1125 if (!descriptor_pool_add_class(descpool,name))
1128 /* add all descriptors in NameAndTypes to the descriptor_pool */
1129 for (nfn=forward_nameandtypes; nfn; nfn=nfn->next) {
1130 utf *desc = class_getconstant(c,nfn->sig_index,CONSTANT_Utf8);
1131 if (!descriptor_pool_add(descpool,desc,NULL))
1135 /* resolve entries in temporary structures */
1137 while (forward_classes) {
1139 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1141 if (opt_verify && !is_valid_name_utf(name)) {
1143 new_classformaterror(c, "Class reference with invalid name");
1147 cptags[forward_classes->thisindex] = CONSTANT_Class;
1148 /* the classref is created later */
1149 cpinfos[forward_classes->thisindex] = name;
1151 nfc = forward_classes;
1152 forward_classes = forward_classes->next;
1155 while (forward_strings) {
1157 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1159 /* resolve utf-string */
1160 cptags[forward_strings->thisindex] = CONSTANT_String;
1161 cpinfos[forward_strings->thisindex] = text;
1163 nfs = forward_strings;
1164 forward_strings = forward_strings->next;
1167 while (forward_nameandtypes) {
1168 constant_nameandtype *cn = NEW(constant_nameandtype);
1170 #if defined(STATISTICS)
1172 count_const_pool_len += sizeof(constant_nameandtype);
1175 /* resolve simple name and descriptor */
1176 cn->name = class_getconstant(c,
1177 forward_nameandtypes->name_index,
1180 cn->descriptor = class_getconstant(c,
1181 forward_nameandtypes->sig_index,
1186 if (!is_valid_name_utf(cn->name)) {
1188 new_classformaterror(c,
1189 "Illegal Field name \"%s\"",
1195 /* disallow referencing <clinit> among others */
1196 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1198 new_exception_utfmessage(string_java_lang_InternalError,
1204 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1205 cpinfos[forward_nameandtypes->thisindex] = cn;
1207 nfn = forward_nameandtypes;
1208 forward_nameandtypes = forward_nameandtypes->next;
1211 while (forward_fieldmethints) {
1212 constant_nameandtype *nat;
1213 constant_FMIref *fmi = NEW(constant_FMIref);
1215 #if defined(STATISTICS)
1217 count_const_pool_len += sizeof(constant_FMIref);
1219 /* resolve simple name and descriptor */
1220 nat = class_getconstant(c,
1221 forward_fieldmethints->nameandtype_index,
1222 CONSTANT_NameAndType);
1224 /* the classref is created later */
1225 fmi->classref = (constant_classref*) (size_t) forward_fieldmethints->class_index;
1226 fmi->name = nat->name;
1227 fmi->descriptor = nat->descriptor;
1229 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1230 cpinfos[forward_fieldmethints->thisindex] = fmi;
1232 nff = forward_fieldmethints;
1233 forward_fieldmethints = forward_fieldmethints->next;
1236 /* everything was ok */
1242 /* load_field ******************************************************************
1244 Load everything about a class field from the class file and fill a
1245 'fieldinfo' structure. For static fields, space in the data segment
1248 *******************************************************************************/
1250 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1252 static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
1257 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1262 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1265 f->flags = suck_u2(cb);
1267 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1271 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1274 f->parseddesc = NULL;
1275 if (!descriptor_pool_add(descpool,u,NULL))
1280 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1281 *exceptionptr = new_classformaterror(c,
1282 "Illegal Field name \"%s\"",
1287 /* check flag consistency */
1288 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1290 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1291 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1293 new_classformaterror(c,
1294 "Illegal field modifiers: 0x%X",
1299 if (c->flags & ACC_INTERFACE) {
1300 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1301 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1302 f->flags & ACC_TRANSIENT) {
1304 new_classformaterror(c,
1305 "Illegal field modifiers: 0x%X",
1312 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1313 f->offset = 0; /* offset from start of object */
1318 case TYPE_INT: f->value.i = 0; break;
1319 case TYPE_FLOAT: f->value.f = 0.0; break;
1320 case TYPE_DOUBLE: f->value.d = 0.0; break;
1321 case TYPE_ADDRESS: f->value.a = NULL; break;
1324 f->value.l = 0; break;
1326 f->value.l.low = 0; f->value.l.high = 0; break;
1330 /* read attributes */
1331 if (!check_classbuffer_size(cb, 2))
1334 attrnum = suck_u2(cb);
1335 for (i = 0; i < attrnum; i++) {
1336 if (!check_classbuffer_size(cb, 2))
1339 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1342 if (u == utf_ConstantValue) {
1343 if (!check_classbuffer_size(cb, 4 + 2))
1346 /* check attribute length */
1347 if (suck_u4(cb) != 2) {
1349 new_classformaterror(c, "Wrong size for VALUE attribute");
1353 /* constant value attribute */
1354 if (pindex != field_load_NOVALUE) {
1356 new_classformaterror(c,
1357 "Multiple ConstantValue attributes");
1361 /* index of value in constantpool */
1362 pindex = suck_u2(cb);
1364 /* initialize field with value from constantpool */
1367 constant_integer *ci;
1369 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1372 f->value.i = ci->value;
1379 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1382 f->value.l = cl->value;
1389 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1392 f->value.f = cf->value;
1397 constant_double *cd;
1399 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1402 f->value.d = cd->value;
1407 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1410 /* create javastring from compressed utf8-string */
1411 f->value.a = literalstring_new(u);
1415 log_text("Invalid Constant - Type");
1419 /* unknown attribute */
1420 if (!skipattributebody(cb))
1425 /* everything was ok */
1431 /* load_method *****************************************************************
1433 Loads a method from the class file and fills an existing
1434 'methodinfo' structure. For native methods, the function pointer
1435 field is set to the real function pointer, for JavaVM methods a
1436 pointer to the compiler is used preliminarily.
1438 *******************************************************************************/
1440 static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool)
1451 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1452 initObjectLock(&m->header);
1457 count_all_methods++;
1460 m->thrownexceptionscount = 0;
1461 m->linenumbercount = 0;
1464 m->nativelyoverloaded = false;
1466 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1469 m->flags = suck_u2(cb);
1471 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1475 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1478 m->parseddesc = NULL;
1479 if (!descriptor_pool_add(descpool,u,&argcount))
1483 if (!is_valid_name_utf(m->name))
1484 panic("Method with invalid name");
1486 if (m->name->text[0] == '<'
1487 && m->name != utf_init && m->name != utf_clinit)
1488 panic("Method with invalid special name");
1491 if (!(m->flags & ACC_STATIC))
1492 argcount++; /* count the 'this' argument */
1495 if (argcount > 255) {
1497 new_classformaterror(c, "Too many arguments in signature");
1501 /* check flag consistency */
1502 if (m->name != utf_clinit) {
1503 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1505 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1507 new_classformaterror(c,
1508 "Illegal method modifiers: 0x%X",
1513 if (m->flags & ACC_ABSTRACT) {
1514 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1515 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1517 new_classformaterror(c,
1518 "Illegal method modifiers: 0x%X",
1524 if (c->flags & ACC_INTERFACE) {
1525 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1527 new_classformaterror(c,
1528 "Illegal method modifiers: 0x%X",
1534 if (m->name == utf_init) {
1535 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1536 ACC_NATIVE | ACC_ABSTRACT))
1537 panic("Instance initialization method has invalid flags set");
1543 m->basicblockcount = 0;
1544 m->basicblocks = NULL;
1545 m->basicblockindex = NULL;
1546 m->instructioncount = 0;
1547 m->instructions = NULL;
1550 m->exceptiontable = NULL;
1551 m->stubroutine = NULL;
1553 m->entrypoint = NULL;
1554 m->methodUsed = NOTUSED;
1557 m->subRedefsUsed = 0;
1561 if (!check_classbuffer_size(cb, 2))
1564 attrnum = suck_u2(cb);
1565 for (i = 0; i < attrnum; i++) {
1568 if (!check_classbuffer_size(cb, 2))
1571 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1574 if (aname == utf_Code) {
1575 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1577 new_classformaterror(c,
1578 "Code attribute in native or abstract methods");
1585 new_classformaterror(c, "Multiple Code attributes");
1590 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1594 m->maxstack = suck_u2(cb);
1595 m->maxlocals = suck_u2(cb);
1597 if (m->maxlocals < argcount) {
1599 new_classformaterror(c, "Arguments can't fit into locals");
1604 if (!check_classbuffer_size(cb, 4))
1607 m->jcodelength = suck_u4(cb);
1609 if (m->jcodelength == 0) {
1611 new_classformaterror(c, "Code of a method has length 0");
1616 if (m->jcodelength > 65535) {
1618 new_classformaterror(c,
1619 "Code of a method longer than 65535 bytes");
1624 if (!check_classbuffer_size(cb, m->jcodelength))
1627 m->jcode = MNEW(u1, m->jcodelength);
1628 suck_nbytes(m->jcode, cb, m->jcodelength);
1630 if (!check_classbuffer_size(cb, 2))
1633 m->exceptiontablelength = suck_u2(cb);
1634 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1637 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1639 #if defined(STATISTICS)
1641 count_vmcode_len += m->jcodelength + 18;
1642 count_extable_len += 8 * m->exceptiontablelength;
1646 for (j = 0; j < m->exceptiontablelength; j++) {
1648 m->exceptiontable[j].startpc = suck_u2(cb);
1649 m->exceptiontable[j].endpc = suck_u2(cb);
1650 m->exceptiontable[j].handlerpc = suck_u2(cb);
1654 m->exceptiontable[j].catchtype.any = NULL;
1657 /* the classref is created later */
1658 if (!(m->exceptiontable[j].catchtype.any =
1659 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1664 if (!check_classbuffer_size(cb, 2))
1667 codeattrnum = suck_u2(cb);
1669 for (; codeattrnum > 0; codeattrnum--) {
1672 if (!check_classbuffer_size(cb, 2))
1675 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1678 if (caname == utf_LineNumberTable) {
1681 if (!check_classbuffer_size(cb, 4 + 2))
1685 m->linenumbercount = suck_u2(cb);
1687 if (!check_classbuffer_size(cb,
1688 (2 + 2) * m->linenumbercount))
1691 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1693 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1694 m->linenumbers[lncid].start_pc = suck_u2(cb);
1695 m->linenumbers[lncid].line_number = suck_u2(cb);
1699 if (!skipattributes(cb, codeattrnum))
1705 if (!skipattributebody(cb))
1710 } else if (aname == utf_Exceptions) {
1713 if (m->thrownexceptions) {
1715 new_classformaterror(c, "Multiple Exceptions attributes");
1719 if (!check_classbuffer_size(cb, 4 + 2))
1722 suck_u4(cb); /* length */
1723 m->thrownexceptionscount = suck_u2(cb);
1725 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1728 m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1730 for (j = 0; j < m->thrownexceptionscount; j++) {
1731 /* the classref is created later */
1732 if (!((m->thrownexceptions)[j].any =
1733 (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1738 if (!skipattributebody(cb))
1743 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1744 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1749 /* everything was ok */
1755 /* load_attribute **************************************************************
1757 Read attributes from classfile.
1759 *******************************************************************************/
1761 static bool load_attributes(classbuffer *cb, u4 num)
1769 for (i = 0; i < num; i++) {
1770 /* retrieve attribute name */
1771 if (!check_classbuffer_size(cb, 2))
1774 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1777 if (aname == utf_InnerClasses) {
1778 /* innerclasses attribute */
1779 if (c->innerclass) {
1781 new_classformaterror(c, "Multiple InnerClasses attributes");
1785 if (!check_classbuffer_size(cb, 4 + 2))
1788 /* skip attribute length */
1791 /* number of records */
1792 c->innerclasscount = suck_u2(cb);
1794 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1797 /* allocate memory for innerclass structure */
1798 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1800 for (j = 0; j < c->innerclasscount; j++) {
1801 /* The innerclass structure contains a class with an encoded
1802 name, its defining scope, its simple name and a bitmask of
1803 the access flags. If an inner class is not a member, its
1804 outer_class is NULL, if a class is anonymous, its name is
1807 innerclassinfo *info = c->innerclass + j;
1809 info->inner_class.ref =
1810 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1811 info->outer_class.ref =
1812 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1814 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1815 info->flags = suck_u2(cb);
1818 } else if (aname == utf_SourceFile) {
1819 if (!check_classbuffer_size(cb, 4 + 2))
1822 if (suck_u4(cb) != 2) {
1824 new_classformaterror(c, "Wrong size for VALUE attribute");
1828 if (c->sourcefile) {
1830 new_classformaterror(c, "Multiple SourceFile attributes");
1834 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1838 /* unknown attribute */
1839 if (!skipattributebody(cb))
1848 /* load_class_from_classloader *************************************************
1850 Load the class with the given name using the given user-defined class loader.
1853 name.............the classname
1854 cl...............user-defined class loader
1858 *result..........set to the loaded class
1861 true.............everything ok
1862 false............an exception has been thrown
1864 *******************************************************************************/
1866 bool load_class_from_classloader(utf *name,java_objectheader *cl,classinfo **result)
1870 LOADER_ASSERT(name);
1871 LOADER_ASSERT(result);
1873 #ifdef LOADER_VERBOSE
1874 fprintf(stderr,"load_class_from_classloader(");
1875 utf_fprint(stderr,name);fprintf(stderr,",%p)\n",(void*)cl);
1878 /* lookup if this class has already been loaded */
1879 *result = classcache_lookup(cl,name);
1883 /* if other class loader than bootstrap, call it */
1888 LOADER_ASSERT(class_java_lang_Object);
1890 lc = class_resolveclassmethod(cl->vftbl->class,
1892 utf_java_lang_String__java_lang_Class,
1893 class_java_lang_Object,
1897 return false; /* exception */
1899 r = (classinfo *) asm_calljavafunction(lc,
1901 javastring_new(name),
1904 /* store this class in the loaded class cache */
1905 if (r && !classcache_store(cl,r)) {
1908 r = NULL; /* exception */
1915 return load_class_bootstrap(name,result);
1919 /* load_class_bootstrap ********************************************************
1921 Load the class with the given name using the bootstrap class loader.
1924 name.............the classname
1927 *result..........set to the loaded class
1930 true.............everything ok
1931 false............an exception has been thrown
1933 *******************************************************************************/
1935 bool load_class_bootstrap(utf *name,classinfo **result)
1941 LOADER_ASSERT(name);
1942 LOADER_ASSERT(result);
1944 /* lookup if this class has already been loaded */
1945 *result = classcache_lookup(NULL,name);
1949 #ifdef LOADER_VERBOSE
1950 fprintf(stderr,"load_class_bootstrap(");
1951 utf_fprint(stderr,name);fprintf(stderr,")\n");
1954 /* create the classinfo */
1955 c = class_new(name);
1957 if (name == utf_java_lang_Object)
1958 class_java_lang_Object = c;
1960 /* store this class in the loaded class cache */
1961 /* XXX we temporarily need this to avoid loading a bootstrap class multiple times */
1962 if (!classcache_store(NULL,c)) {
1973 #if defined(USE_THREADS)
1974 /* enter a monitor on the class */
1976 builtin_monitorenter((java_objectheader *) c);
1979 #if defined(STATISTICS)
1981 if (getcompilingtime)
1982 compilingtime_stop();
1985 loadingtime_start();
1988 /* load classdata, throw exception on error */
1990 if ((cb = suck_start(c)) == NULL) {
1991 /* this means, the classpath was not set properly */
1992 if (name == utf_java_lang_Object)
1993 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1994 "java/lang/Object");
1997 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2000 #if defined(USE_THREADS)
2001 builtin_monitorexit((java_objectheader *) c);
2007 /* load the class from the buffer */
2009 r = load_class_from_classbuffer(cb);
2011 /* if return value is NULL, we had a problem and the class is not loaded */
2015 /* now free the allocated memory, otherwise we could ran into a DOS */
2022 #if defined(STATISTICS)
2027 if (getcompilingtime)
2028 compilingtime_start();
2032 /* store this class in the loaded class cache */
2033 if (r && !classcache_store(NULL,c)) {
2036 r = NULL; /* exception */
2040 #if defined(USE_THREADS)
2041 /* leave the monitor */
2042 builtin_monitorexit((java_objectheader *) c);
2050 /* load_class_from_classbuffer *************************************************
2052 Loads everything interesting about a class from the class file. The
2053 'classinfo' structure must have been allocated previously.
2055 The super class and the interfaces implemented by this class need
2056 not be loaded. The link is set later by the function 'class_link'.
2058 The loaded class is removed from the list 'unloadedclasses' and
2059 added to the list 'unlinkedclasses'.
2061 *******************************************************************************/
2063 classinfo *load_class_from_classbuffer(classbuffer *cb)
2071 descriptor_pool *descpool;
2072 char msg[MAXLOGTEXT]; /* maybe we get an exception */
2073 #if defined(STATISTICS)
2078 /* get the classbuffer's class */
2081 /* maybe the class is already loaded */
2085 #if defined(STATISTICS)
2087 count_class_loads++;
2090 /* output for debugging purposes */
2092 log_message_class("Loading class: ", c);
2094 /* mark start of dump memory area */
2095 dumpsize = dump_size();
2097 /* class is somewhat loaded */
2100 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2101 goto return_exception;
2103 /* check signature */
2104 if (suck_u4(cb) != MAGIC) {
2105 *exceptionptr = new_classformaterror(c, "Bad magic number");
2107 goto return_exception;
2114 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2116 new_unsupportedclassversionerror(c,
2117 "Unsupported major.minor version %d.%d",
2120 goto return_exception;
2123 /* create a new descriptor pool */
2124 descpool = descriptor_pool_new(c);
2126 /* load the constant pool */
2127 if (!load_constantpool(cb,descpool))
2128 goto return_exception;
2131 c->erroneous_state = 0;
2132 c->initializing_thread = 0;
2134 c->classUsed = NOTUSED; /* not used initially CO-RT */
2138 if (!check_classbuffer_size(cb, 2))
2139 goto return_exception;
2141 c->flags = suck_u2(cb);
2142 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
2144 /* check ACC flags consistency */
2145 if (c->flags & ACC_INTERFACE) {
2146 if (!(c->flags & ACC_ABSTRACT)) {
2147 /* We work around this because interfaces in JDK 1.1 are
2148 * not declared abstract. */
2150 c->flags |= ACC_ABSTRACT;
2151 /* panic("Interface class not declared abstract"); */
2154 if (c->flags & ACC_FINAL) {
2156 new_classformaterror(c,
2157 "Illegal class modifiers: 0x%X", c->flags);
2159 goto return_exception;
2162 if (c->flags & ACC_SUPER) {
2163 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2167 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2169 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2171 goto return_exception;
2174 if (!check_classbuffer_size(cb, 2 + 2))
2175 goto return_exception;
2179 if (!(name = (utf*) class_getconstant(c, i, CONSTANT_Class)))
2180 goto return_exception;
2182 if (name != c->name) {
2183 utf_sprint(msg, c->name);
2184 sprintf(msg + strlen(msg), " (wrong name: ");
2185 utf_sprint(msg + strlen(msg), name);
2186 sprintf(msg + strlen(msg), ")");
2189 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2191 goto return_exception;
2194 /* retrieve superclass */
2195 c->super.any = NULL;
2196 if ((i = suck_u2(cb))) {
2197 if (!(supername = (utf*) class_getconstant(c, i, CONSTANT_Class)))
2198 goto return_exception;
2200 /* java.lang.Object may not have a super class. */
2201 if (c->name == utf_java_lang_Object) {
2203 new_exception_message(string_java_lang_ClassFormatError,
2204 "java.lang.Object with superclass");
2206 goto return_exception;
2209 /* Interfaces must have java.lang.Object as super class. */
2210 if ((c->flags & ACC_INTERFACE) &&
2211 supername != utf_java_lang_Object) {
2213 new_exception_message(string_java_lang_ClassFormatError,
2214 "Interfaces must have java.lang.Object as superclass");
2216 goto return_exception;
2222 /* This is only allowed for java.lang.Object. */
2223 if (c->name != utf_java_lang_Object) {
2224 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2226 goto return_exception;
2230 /* retrieve interfaces */
2231 if (!check_classbuffer_size(cb, 2))
2232 goto return_exception;
2234 c->interfacescount = suck_u2(cb);
2236 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2237 goto return_exception;
2239 c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
2240 for (i = 0; i < c->interfacescount; i++) {
2241 /* the classrefs are created later */
2242 if (!(c->interfaces[i].any = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2243 goto return_exception;
2247 if (!check_classbuffer_size(cb, 2))
2248 goto return_exception;
2250 c->fieldscount = suck_u2(cb);
2251 c->fields = GCNEW(fieldinfo, c->fieldscount);
2252 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2253 for (i = 0; i < c->fieldscount; i++) {
2254 if (!load_field(cb, &(c->fields[i]),descpool))
2255 goto return_exception;
2259 if (!check_classbuffer_size(cb, 2))
2260 goto return_exception;
2262 c->methodscount = suck_u2(cb);
2263 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2264 c->methods = MNEW(methodinfo, c->methodscount);
2265 for (i = 0; i < c->methodscount; i++) {
2266 if (!load_method(cb, &(c->methods[i]),descpool))
2267 goto return_exception;
2270 /* create the class reference table */
2271 c->classrefs = descriptor_pool_create_classrefs(descpool,&(c->classrefcount));
2273 /* allocate space for the parsed descriptors */
2274 descriptor_pool_alloc_parsed_descriptors(descpool);
2275 c->parseddescs = descriptor_pool_get_parsed_descriptors(descpool,&(c->parseddescsize));
2277 #if defined(STATISTICS)
2279 descriptor_pool_get_sizes(descpool,&classrefsize,&descsize);
2280 count_classref_len += classrefsize;
2281 count_parsed_desc_len += descsize;
2285 /* put the classrefs in the constant pool */
2286 for (i=0; i<c->cpcount; ++i) {
2287 if (c->cptags[i] == CONSTANT_Class) {
2288 utf *name = (utf*) c->cpinfos[i];
2289 c->cpinfos[i] = descriptor_pool_lookup_classref(descpool,name);
2293 /* set the super class reference */
2295 c->super.ref = descriptor_pool_lookup_classref(descpool,supername);
2297 goto return_exception;
2300 /* set the super interfaces references */
2301 for (i=0; i<c->interfacescount; ++i) {
2302 c->interfaces[i].ref = descriptor_pool_lookup_classref(descpool,(utf*)c->interfaces[i].any);
2303 if (!c->interfaces[i].ref)
2304 goto return_exception;
2307 /* parse the loaded descriptors */
2308 for (i=0; i<c->cpcount; ++i) {
2309 constant_FMIref *fmi;
2312 switch (c->cptags[i]) {
2313 case CONSTANT_Fieldref:
2314 fmi = (constant_FMIref *)c->cpinfos[i];
2315 fmi->parseddesc.fd =
2316 descriptor_pool_parse_field_descriptor(descpool,fmi->descriptor);
2317 if (!fmi->parseddesc.fd)
2318 goto return_exception;
2319 index = (int) (size_t) fmi->classref;
2320 fmi->classref = (constant_classref*)class_getconstant(c,index,CONSTANT_Class);
2322 goto return_exception;
2324 case CONSTANT_Methodref:
2325 case CONSTANT_InterfaceMethodref:
2326 fmi = (constant_FMIref *)c->cpinfos[i];
2327 fmi->parseddesc.md =
2328 descriptor_pool_parse_method_descriptor(descpool,fmi->descriptor);
2329 if (!fmi->parseddesc.md)
2330 goto return_exception;
2331 index = (int) (size_t) fmi->classref;
2332 fmi->classref = (constant_classref*)class_getconstant(c,index,CONSTANT_Class);
2334 goto return_exception;
2338 for (i = 0; i < c->fieldscount; i++) {
2339 c->fields[i].parseddesc = descriptor_pool_parse_field_descriptor(descpool,c->fields[i].descriptor);
2340 if (!c->fields[i].parseddesc)
2341 goto return_exception;
2343 for (i = 0; i < c->methodscount; i++) {
2344 methodinfo *m = c->methods + i;
2345 m->parseddesc = descriptor_pool_parse_method_descriptor(descpool,m->descriptor);
2347 goto return_exception;
2349 for (j=0; j<m->exceptiontablelength; ++j) {
2350 if (!m->exceptiontable[j].catchtype.any)
2352 if ((m->exceptiontable[j].catchtype.ref = descriptor_pool_lookup_classref(descpool,
2353 (utf*)m->exceptiontable[j].catchtype.any)) == NULL)
2354 goto return_exception;
2356 for (j=0; j<m->thrownexceptionscount; ++j) {
2357 if (!m->thrownexceptions[j].any)
2359 if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2360 (utf*)m->thrownexceptions[j].any)) == NULL)
2361 goto return_exception;
2365 /* Check if all fields and methods can be uniquely
2366 * identified by (name,descriptor). */
2368 /* We use a hash table here to avoid making the
2369 * average case quadratic in # of methods, fields.
2371 static int shift = 0;
2373 u2 *next; /* for chaining colliding hash entries */
2379 /* Allocate hashtable */
2380 len = c->methodscount;
2381 if (len < c->fieldscount) len = c->fieldscount;
2383 hashtab = MNEW(u2,(hashlen + len));
2384 next = hashtab + hashlen;
2386 /* Determine bitshift (to get good hash values) */
2396 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2398 for (i = 0; i < c->fieldscount; ++i) {
2399 fieldinfo *fi = c->fields + i;
2401 /* It's ok if we lose bits here */
2402 index = ((((size_t) fi->name) +
2403 ((size_t) fi->descriptor)) >> shift) % hashlen;
2405 if ((old = hashtab[index])) {
2409 if (c->fields[old].name == fi->name &&
2410 c->fields[old].descriptor == fi->descriptor) {
2412 new_classformaterror(c,
2413 "Repetitive field name/signature");
2415 goto return_exception;
2417 } while ((old = next[old]));
2419 hashtab[index] = i + 1;
2423 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2425 for (i = 0; i < c->methodscount; ++i) {
2426 methodinfo *mi = c->methods + i;
2428 /* It's ok if we lose bits here */
2429 index = ((((size_t) mi->name) +
2430 ((size_t) mi->descriptor)) >> shift) % hashlen;
2434 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2435 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2439 if ((old = hashtab[index])) {
2443 if (c->methods[old].name == mi->name &&
2444 c->methods[old].descriptor == mi->descriptor) {
2446 new_classformaterror(c,
2447 "Repetitive method name/signature");
2449 goto return_exception;
2451 } while ((old = next[old]));
2453 hashtab[index] = i + 1;
2456 MFREE(hashtab, u2, (hashlen + len));
2459 #if defined(STATISTICS)
2461 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2462 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2463 count_class_infos += sizeof(methodinfo) * c->methodscount;
2467 /* load attribute structures */
2468 if (!check_classbuffer_size(cb, 2))
2469 goto return_exception;
2471 if (!load_attributes(cb, suck_u2(cb)))
2472 goto return_exception;
2475 /* Pre java 1.5 version don't check this. This implementation is like
2476 java 1.5 do it: for class file version 45.3 we don't check it, older
2477 versions are checked.
2479 if ((ma == 45 && mi > 3) || ma > 45) {
2480 /* check if all data has been read */
2481 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2483 if (classdata_left > 0) {
2485 new_classformaterror(c, "Extra bytes at the end of class file");
2486 goto return_exception;
2491 /* release dump area */
2492 dump_release(dumpsize);
2495 log_message_class("Loading done class: ", c);
2500 /* release dump area */
2501 dump_release(dumpsize);
2503 /* an exception has been thrown */
2509 /******************* Function: class_new_array *********************************
2511 This function is called by class_new to setup an array class.
2513 *******************************************************************************/
2515 void class_new_array(classinfo *c)
2517 classinfo *comp = NULL;
2519 methoddesc *clonedesc;
2520 constant_classref *classrefs;
2523 /* Check array class name */
2524 namelen = c->name->blength;
2525 if (namelen < 2 || c->name->text[0] != '[')
2526 panic("Invalid array class name");
2528 /* Check the component type */
2529 switch (c->name->text[1]) {
2531 /* c is an array of arrays. We have to create the component class. */
2533 comp = class_new_intern(utf_new_intern(c->name->text + 1,
2535 LOADER_ASSERT(comp->loaded);
2536 list_addfirst(&unlinkedclasses, comp);
2539 comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2544 /* c is an array of objects. */
2545 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2546 panic("Invalid array class name");
2549 comp = class_new_intern(utf_new_intern(c->name->text + 2,
2551 LOADER_ASSERT(comp->loaded);
2552 list_addfirst(&unlinkedclasses, comp);
2555 comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2560 LOADER_ASSERT(class_java_lang_Object);
2561 LOADER_ASSERT(class_java_lang_Cloneable);
2562 LOADER_ASSERT(class_java_io_Serializable);
2564 /* Setup the array class */
2565 c->super.cls = class_java_lang_Object;
2566 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2568 c->interfacescount = 2;
2569 c->interfaces = MNEW(classref_or_classinfo, 2);
2574 tc = class_java_lang_Cloneable;
2575 LOADER_ASSERT(tc->loaded);
2576 list_addfirst(&unlinkedclasses, tc);
2577 c->interfaces[0].cls = tc;
2579 tc = class_java_io_Serializable;
2580 LOADER_ASSERT(tc->loaded);
2581 list_addfirst(&unlinkedclasses, tc);
2582 c->interfaces[1].cls = tc;
2585 c->interfaces[0].cls = class_java_lang_Cloneable;
2586 c->interfaces[1].cls = class_java_io_Serializable;
2589 c->methodscount = 1;
2590 c->methods = MNEW(methodinfo, c->methodscount);
2592 classrefs = MNEW(constant_classref,1);
2593 CLASSREF_INIT(classrefs[0],c,utf_java_lang_Object);
2595 clonedesc = NEW(methoddesc);
2596 clonedesc->returntype.type = TYPE_ADDRESS;
2597 clonedesc->returntype.classref = classrefs;
2598 clonedesc->returntype.arraydim = 0;
2599 clonedesc->paramcount = 0;
2600 clonedesc->paramslots = 0;
2603 MSET(clone, 0, methodinfo, 1);
2604 clone->flags = ACC_PUBLIC;
2605 clone->name = utf_new_char("clone");
2606 clone->descriptor = utf_void__java_lang_Object;
2607 clone->parseddesc = clonedesc;
2609 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2610 clone->monoPoly = MONO;
2612 /* XXX: field: length? */
2614 /* array classes are not loaded from class files */
2616 c->parseddescs = (u1*) clonedesc;
2617 c->parseddescsize = sizeof(methodinfo);
2618 c->classrefs = classrefs;
2619 c->classrefcount = 1;
2621 /* XXX insert class into the loaded class cache */
2625 /************************* Function: class_findfield ***************************
2627 Searches a 'classinfo' structure for a field having the given name and
2630 *******************************************************************************/
2632 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2636 for (i = 0; i < c->fieldscount; i++) {
2637 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2638 return &(c->fields[i]);
2641 panic("Can not find field given in CONSTANT_Fieldref");
2643 /* keep compiler happy */
2648 /****************** Function: class_resolvefield_int ***************************
2650 This is an internally used helper function. Do not use this directly.
2652 Tries to resolve a field having the given name and type.
2653 If the field cannot be resolved, NULL is returned.
2655 *******************************************************************************/
2657 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2662 /* search for field in class c */
2664 for (i = 0; i < c->fieldscount; i++) {
2665 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2666 return &(c->fields[i]);
2670 /* try superinterfaces recursively */
2672 for (i = 0; i < c->interfacescount; i++) {
2673 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
2678 /* try superclass */
2681 return class_resolvefield_int(c->super.cls, name, desc);
2689 /********************* Function: class_resolvefield ***************************
2691 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2693 If the field cannot be resolved the return value is NULL. If EXCEPT is
2694 true *exceptionptr is set, too.
2696 *******************************************************************************/
2698 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2699 classinfo *referer, bool except)
2703 /* XXX resolve class c */
2704 /* XXX check access from REFERER to C */
2706 fi = class_resolvefield_int(c, name, desc);
2711 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2717 /* XXX check access rights */
2723 /* class_findmethod ************************************************************
2725 Searches a 'classinfo' structure for a method having the given name
2726 and descriptor. If descriptor is NULL, it is ignored.
2728 *******************************************************************************/
2730 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2735 for (i = 0; i < c->methodscount; i++) {
2736 m = &(c->methods[i]);
2738 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
2746 /*********************** Function: class_fetchmethod **************************
2748 like class_findmethod, but aborts with an error if the method is not found
2750 *******************************************************************************/
2752 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2756 mi = class_findmethod(c, name, desc);
2759 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2760 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2761 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2762 panic("Method not found");
2769 /************************* Function: class_findmethod_approx ******************
2771 like class_findmethod but ignores the return value when comparing the
2774 *******************************************************************************/
2776 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2780 for (i = 0; i < c->methodscount; i++) {
2781 if (c->methods[i].name == name) {
2782 utf *meth_descr = c->methods[i].descriptor;
2786 return &(c->methods[i]);
2788 if (desc->blength <= meth_descr->blength) {
2789 /* current position in utf text */
2790 char *desc_utf_ptr = desc->text;
2791 char *meth_utf_ptr = meth_descr->text;
2792 /* points behind utf strings */
2793 char *desc_end = utf_end(desc);
2794 char *meth_end = utf_end(meth_descr);
2797 /* compare argument types */
2798 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2800 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2801 break; /* no match */
2804 return &(c->methods[i]); /* all parameter types equal */
2814 /***************** Function: class_resolvemethod_approx ***********************
2816 Searches a class and every super class for a method (without paying
2817 attention to the return value)
2819 *******************************************************************************/
2821 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2824 /* search for method (ignore returntype) */
2825 methodinfo *m = class_findmethod_approx(c, name, desc);
2828 /* search superclass */
2836 /* class_resolvemethod *********************************************************
2838 Searches a class and it's super classes for a method.
2840 *******************************************************************************/
2842 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2847 m = class_findmethod(c, name, desc);
2859 /* class_resolveinterfacemethod_intern *****************************************
2861 Internally used helper function. Do not use this directly.
2863 *******************************************************************************/
2865 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
2866 utf *name, utf *desc)
2871 m = class_findmethod(c, name, desc);
2876 /* try the superinterfaces */
2878 for (i = 0; i < c->interfacescount; i++) {
2879 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls, name, desc);
2888 /* class_resolveinterfacemethod ************************************************
2890 Resolves a reference from REFERER to a method with NAME and DESC in
2893 If the method cannot be resolved the return value is NULL. If
2894 EXCEPT is true *exceptionptr is set, too.
2896 *******************************************************************************/
2898 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2899 classinfo *referer, bool except)
2903 /* XXX resolve class c */
2904 /* XXX check access from REFERER to C */
2906 if (!(c->flags & ACC_INTERFACE)) {
2909 new_exception(string_java_lang_IncompatibleClassChangeError);
2914 mi = class_resolveinterfacemethod_intern(c, name, desc);
2919 /* try class java.lang.Object */
2920 LOADER_ASSERT(class_java_lang_Object);
2921 mi = class_findmethod(class_java_lang_Object, name, desc);
2928 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
2934 /* class_resolveclassmethod ****************************************************
2936 Resolves a reference from REFERER to a method with NAME and DESC in
2939 If the method cannot be resolved the return value is NULL. If EXCEPT is
2940 true *exceptionptr is set, too.
2942 *******************************************************************************/
2944 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
2945 classinfo *referer, bool except)
2953 /* XXX resolve class c */
2954 /* XXX check access from REFERER to C */
2956 /* if (c->flags & ACC_INTERFACE) { */
2958 /* *exceptionptr = */
2959 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
2963 /* try class c and its superclasses */
2968 mi = class_findmethod(cls, name, desc);
2973 cls = cls->super.cls;
2976 /* try the superinterfaces */
2978 for (i = 0; i < c->interfacescount; i++) {
2979 mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls, name, desc);
2986 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
2987 utf_strlen(desc) + strlen("0");
2989 msg = MNEW(char, msglen);
2991 utf_sprint(msg, c->name);
2993 utf_sprint(msg + strlen(msg), name);
2994 utf_sprint(msg + strlen(msg), desc);
2997 new_exception_message(string_java_lang_NoSuchMethodError, msg);
2999 MFREE(msg, char, msglen);
3005 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
3007 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
3012 /* XXX check access rights */
3018 /************************* Function: class_issubclass **************************
3020 Checks if sub is a descendant of super.
3022 *******************************************************************************/
3024 bool class_issubclass(classinfo *sub, classinfo *super)
3027 if (!sub) return false;
3028 if (sub == super) return true;
3029 sub = sub->super.cls;
3034 /****************** Initialization function for classes ******************
3036 In Java, every class can have a static initialization function. This
3037 function has to be called BEFORE calling other methods or accessing static
3040 *******************************************************************************/
3042 static classinfo *class_init_intern(classinfo *c);
3044 classinfo *class_init(classinfo *c)
3048 if (!makeinitializations)
3051 #if defined(USE_THREADS)
3052 /* enter a monitor on the class */
3054 builtin_monitorenter((java_objectheader *) c);
3057 /* maybe the class is already initalized or the current thread, which can
3058 pass the monitor, is currently initalizing this class */
3060 /* JOWENN: In future we need an additinal flag: initializationfailed,
3061 since further access to the class should cause a NoClassDefFound,
3062 if the static initializer failed once
3065 if (c->initialized || c->initializing) {
3066 #if defined(USE_THREADS)
3067 builtin_monitorexit((java_objectheader *) c);
3073 /* this initalizing run begins NOW */
3074 c->initializing = true;
3076 /* call the internal function */
3077 r = class_init_intern(c);
3079 /* if return value is not NULL everything was ok and the class is
3082 c->initialized = true;
3084 /* this initalizing run is done */
3085 c->initializing = false;
3087 #if defined(USE_THREADS)
3088 /* leave the monitor */
3090 builtin_monitorexit((java_objectheader *) c);
3097 /* this function MUST NOT be called directly, because of thread <clinit>
3100 static classinfo *class_init_intern(classinfo *c)
3104 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3109 LOADER_ASSERT(c->loaded);
3111 /* maybe the class is not already linked */
3116 #if defined(STATISTICS)
3118 count_class_inits++;
3121 /* initialize super class */
3124 if (!c->super.cls->initialized) {
3126 char logtext[MAXLOGTEXT];
3127 sprintf(logtext, "Initialize super class ");
3128 utf_sprint_classname(logtext + strlen(logtext), c->super.cls->name);
3129 sprintf(logtext + strlen(logtext), " from ");
3130 utf_sprint_classname(logtext + strlen(logtext), c->name);
3134 if (!class_init(c->super.cls))
3139 /* initialize interface classes */
3141 for (i = 0; i < c->interfacescount; i++) {
3142 if (!c->interfaces[i].cls->initialized) {
3144 char logtext[MAXLOGTEXT];
3145 sprintf(logtext, "Initialize interface class ");
3146 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i].cls->name);
3147 sprintf(logtext + strlen(logtext), " from ");
3148 utf_sprint_classname(logtext + strlen(logtext), c->name);
3152 if (!class_init(c->interfaces[i].cls))
3157 m = class_findmethod(c, utf_clinit, utf_void__void);
3161 char logtext[MAXLOGTEXT];
3162 sprintf(logtext, "Class ");
3163 utf_sprint_classname(logtext + strlen(logtext), c->name);
3164 sprintf(logtext + strlen(logtext), " has no static class initializer");
3171 /* Sun's and IBM's JVM don't care about the static flag */
3172 /* if (!(m->flags & ACC_STATIC)) { */
3173 /* panic("Class initializer is not static!"); */
3176 log_message_class("Starting static class initializer for class: ", c);
3178 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3183 /* now call the initializer */
3184 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3186 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3187 assert(blockInts == 0);
3191 /* we have an exception or error */
3192 if (*exceptionptr) {
3193 /* class is NOT initialized */
3194 c->initialized = false;
3196 /* is this an exception, than wrap it */
3197 LOADER_ASSERT(class_java_lang_Exception);
3198 if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
3199 java_objectheader *xptr;
3200 java_objectheader *cause;
3203 cause = *exceptionptr;
3205 /* clear exception, because we are calling jit code again */
3206 *exceptionptr = NULL;
3208 /* wrap the exception */
3210 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3211 (java_lang_Throwable *) cause);
3213 /* XXX should we exit here? */
3217 /* set new exception */
3218 *exceptionptr = xptr;
3225 log_message_class("Finished static class initializer for class: ", c);
3231 void class_showconstanti(classinfo *c, int ii)
3237 printf ("#%d: ", (int) i);
3239 switch (c->cptags [i]) {
3240 case CONSTANT_Class:
3241 printf("Classreference -> ");
3242 utf_display(((constant_classref*)e)->name);
3245 case CONSTANT_Fieldref:
3246 printf("Fieldref -> "); goto displayFMIi;
3247 case CONSTANT_Methodref:
3248 printf("Methodref -> "); goto displayFMIi;
3249 case CONSTANT_InterfaceMethodref:
3250 printf("InterfaceMethod -> "); goto displayFMIi;
3253 constant_FMIref *fmi = e;
3254 utf_display(fmi->classref->name);
3256 utf_display(fmi->name);
3258 utf_display(fmi->descriptor);
3262 case CONSTANT_String:
3263 printf("String -> ");
3266 case CONSTANT_Integer:
3267 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3269 case CONSTANT_Float:
3270 printf("Float -> %f", ((constant_float*)e)->value);
3272 case CONSTANT_Double:
3273 printf("Double -> %f", ((constant_double*)e)->value);
3277 u8 v = ((constant_long*)e)->value;
3279 printf("Long -> %ld", (long int) v);
3281 printf("Long -> HI: %ld, LO: %ld\n",
3282 (long int) v.high, (long int) v.low);
3286 case CONSTANT_NameAndType:
3288 constant_nameandtype *cnt = e;
3289 printf("NameAndType: ");
3290 utf_display(cnt->name);
3292 utf_display(cnt->descriptor);
3300 panic("Invalid type of ConstantPool-Entry");
3307 void class_showconstantpool (classinfo *c)
3312 printf ("---- dump of constant pool ----\n");
3314 for (i=0; i<c->cpcount; i++) {
3315 printf ("#%d: ", (int) i);
3317 e = c -> cpinfos [i];
3320 switch (c -> cptags [i]) {
3321 case CONSTANT_Class:
3322 printf ("Classreference -> ");
3323 utf_display ( ((constant_classref*)e) -> name );
3326 case CONSTANT_Fieldref:
3327 printf ("Fieldref -> "); goto displayFMI;
3328 case CONSTANT_Methodref:
3329 printf ("Methodref -> "); goto displayFMI;
3330 case CONSTANT_InterfaceMethodref:
3331 printf ("InterfaceMethod -> "); goto displayFMI;
3334 constant_FMIref *fmi = e;
3335 utf_display ( fmi->classref->name );
3337 utf_display ( fmi->name);
3339 utf_display ( fmi->descriptor );
3343 case CONSTANT_String:
3344 printf ("String -> ");
3347 case CONSTANT_Integer:
3348 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3350 case CONSTANT_Float:
3351 printf ("Float -> %f", ((constant_float*)e) -> value);
3353 case CONSTANT_Double:
3354 printf ("Double -> %f", ((constant_double*)e) -> value);
3358 u8 v = ((constant_long*)e) -> value;
3360 printf ("Long -> %ld", (long int) v);
3362 printf ("Long -> HI: %ld, LO: %ld\n",
3363 (long int) v.high, (long int) v.low);
3367 case CONSTANT_NameAndType:
3369 constant_nameandtype *cnt = e;
3370 printf ("NameAndType: ");
3371 utf_display (cnt->name);
3373 utf_display (cnt->descriptor);
3377 printf ("Utf8 -> ");
3381 panic ("Invalid type of ConstantPool-Entry");
3391 /********** Function: class_showmethods (debugging only) *************/
3393 void class_showmethods (classinfo *c)
3397 printf ("--------- Fields and Methods ----------------\n");
3398 printf ("Flags: "); printflags (c->flags); printf ("\n");
3400 printf ("This: "); utf_display (c->name); printf ("\n");
3402 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
3404 printf ("Index: %d\n", c->index);
3406 printf ("interfaces:\n");
3407 for (i=0; i < c-> interfacescount; i++) {
3409 utf_display (c -> interfaces[i].cls -> name);
3410 printf (" (%d)\n", c->interfaces[i].cls -> index);
3413 printf ("fields:\n");
3414 for (i=0; i < c -> fieldscount; i++) {
3415 field_display (&(c -> fields[i]));
3418 printf ("methods:\n");
3419 for (i=0; i < c -> methodscount; i++) {
3420 methodinfo *m = &(c->methods[i]);
3421 if ( !(m->flags & ACC_STATIC))
3422 printf ("vftblindex: %d ", m->vftblindex);
3424 method_display ( m );
3428 printf ("Virtual function table:\n");
3429 for (i=0; i<c->vftbl->vftbllength; i++) {
3430 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3436 /******************************************************************************/
3437 /******************* General functions for the class loader *******************/
3438 /******************************************************************************/
3440 /******************** Function: loader_close ***********************************
3444 *******************************************************************************/
3451 for (slot = 0; slot < class_hash.size; slot++) {
3452 c = class_hash.ptr[slot];
3463 * These are local overrides for various environment variables in Emacs.
3464 * Please do not remove this and leave it at the end of the file, where
3465 * Emacs will automagically detect them.
3466 * ---------------------------------------------------------------------
3469 * indent-tabs-mode: t