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 2155 2005-03-30 20:04:42Z twisti $
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"
72 # include "vm/unzip.h"
75 #include "vm/jit/asmpart.h"
76 #include "vm/jit/codegen.inc.h"
84 /********************************************************************
85 list of classpath entries (either filesystem directories or
87 ********************************************************************/
89 classpath_info *classpath_entries = NULL;
92 /******************* function: checkfielddescriptor ****************************
94 checks whether a field-descriptor is valid and aborts otherwise
95 all referenced classes are inserted into the list of unloaded classes
97 *******************************************************************************/
99 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
101 class_from_descriptor(utf_ptr,end_pos,NULL,
103 | CLASSLOAD_NULLPRIMITIVE
105 | CLASSLOAD_CHECKEND);
107 /* XXX use the following if -noverify */
109 char *tstart; /* pointer to start of classname */
111 char *start = utf_ptr;
113 switch (*utf_ptr++) {
127 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
128 panic ("Ill formed descriptor");
132 panic ("Ill formed descriptor");
135 /* exceeding characters */
136 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
141 /******************* function checkmethoddescriptor ****************************
143 checks whether a method-descriptor is valid and aborts otherwise.
144 All referenced classes are inserted into the list of unloaded classes.
146 The number of arguments is returned. A long or double argument is counted
149 *******************************************************************************/
151 static int checkmethoddescriptor(classinfo *c, utf *descriptor)
153 char *utf_ptr; /* current position in utf text */
154 char *end_pos; /* points behind utf string */
155 s4 argcount = 0; /* number of arguments */
157 utf_ptr = descriptor->text;
158 end_pos = utf_end(descriptor);
160 /* method descriptor must start with parenthesis */
161 if (utf_ptr == end_pos || *utf_ptr++ != '(')
162 panic ("Missing '(' in method descriptor");
164 /* check arguments */
165 while (utf_ptr != end_pos && *utf_ptr != ')') {
166 /* We cannot count the this argument here because
167 * we don't know if the method is static. */
168 if (*utf_ptr == 'J' || *utf_ptr == 'D')
172 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
174 | CLASSLOAD_NULLPRIMITIVE
178 if (utf_ptr == end_pos)
179 panic("Missing ')' in method descriptor");
181 utf_ptr++; /* skip ')' */
183 class_from_descriptor(utf_ptr,
187 CLASSLOAD_NULLPRIMITIVE |
190 if (argcount > 255) {
192 new_classformaterror(c, "Too many arguments in signature");
199 /* XXX use the following if -noverify */
201 /* check arguments */
202 while ((c = *utf_ptr++) != ')') {
219 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
220 panic ("Ill formed method descriptor");
224 panic ("Ill formed methodtype-descriptor");
228 /* check returntype */
230 /* returntype void */
231 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
234 /* treat as field-descriptor */
235 checkfielddescriptor (utf_ptr,end_pos);
240 /* loader_init *****************************************************************
242 Initializes all lists and loads all classes required for the system
245 *******************************************************************************/
247 bool loader_init(u1 *stackbottom)
251 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
252 /* Initialize the monitor pointer for zip/jar file locking. */
254 for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
255 if (cpi->type == CLASSPATH_ARCHIVE)
256 initObjectLock(&cpi->header);
260 /* load some important classes */
262 if (!load_class_bootstrap(class_java_lang_Object))
265 if (!load_class_bootstrap(class_java_lang_String))
268 if (!load_class_bootstrap(class_java_lang_Cloneable))
271 if (!load_class_bootstrap(class_java_io_Serializable))
275 /* load classes for wrapping primitive types */
277 if (!load_class_bootstrap(class_java_lang_Void))
280 if (!load_class_bootstrap(class_java_lang_Boolean))
283 if (!load_class_bootstrap(class_java_lang_Byte))
286 if (!load_class_bootstrap(class_java_lang_Character))
289 if (!load_class_bootstrap(class_java_lang_Short))
292 if (!load_class_bootstrap(class_java_lang_Integer))
295 if (!load_class_bootstrap(class_java_lang_Long))
298 if (!load_class_bootstrap(class_java_lang_Float))
301 if (!load_class_bootstrap(class_java_lang_Double))
305 #if defined(USE_THREADS)
306 if (stackbottom != 0)
314 /************* functions for reading classdata *********************************
316 getting classdata in blocks of variable size
317 (8,16,32,64-bit integer or float)
319 *******************************************************************************/
321 /* check_classbuffer_size ******************************************************
323 assert that at least <len> bytes are left to read
324 <len> is limited to the range of non-negative s4 values
326 *******************************************************************************/
328 inline bool check_classbuffer_size(classbuffer *cb, s4 len)
330 if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
332 new_classformaterror((cb)->class, "Truncated class file");
341 /* suck_nbytes *****************************************************************
343 transfer block of classfile data into a buffer
345 *******************************************************************************/
347 inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
349 memcpy(buffer, cb->pos + 1, len);
354 /* skip_nbytes ****************************************************************
356 skip block of classfile data
358 *******************************************************************************/
360 inline void skip_nbytes(classbuffer *cb, s4 len)
366 inline u1 suck_u1(classbuffer *cb)
372 inline u2 suck_u2(classbuffer *cb)
376 return ((u2) a << 8) + (u2) b;
380 inline u4 suck_u4(classbuffer *cb)
386 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
390 /* get u8 from classfile data */
391 static u8 suck_u8(classbuffer *cb)
397 return (hi << 32) + lo;
400 v.high = suck_u4(cb);
407 /* get float from classfile data */
408 static float suck_float(classbuffer *cb)
416 for (i = 0; i < 4; i++)
417 buffer[3 - i] = suck_u1(cb);
419 memcpy((u1*) (&f), buffer, 4);
421 suck_nbytes((u1*) (&f), cb, 4);
424 if (sizeof(float) != 4) {
425 *exceptionptr = new_exception_message(string_java_lang_InternalError,
426 "Incompatible float-format");
428 /* XXX should we exit in such a case? */
429 throw_exception_exit();
436 /* get double from classfile data */
437 static double suck_double(classbuffer *cb)
445 for (i = 0; i < 8; i++)
446 buffer[7 - i] = suck_u1(cb);
448 memcpy((u1*) (&d), buffer, 8);
450 suck_nbytes((u1*) (&d), cb, 8);
453 if (sizeof(double) != 8) {
454 *exceptionptr = new_exception_message(string_java_lang_InternalError,
455 "Incompatible double-format");
457 /* XXX should we exit in such a case? */
458 throw_exception_exit();
465 /************************** function suck_init *********************************
467 called once at startup, sets the searchpath for the classfiles
469 *******************************************************************************/
471 void suck_init(char *classpath)
479 classpath_info *lastcpi;
483 /* search for last classpath entry (only if there already some) */
485 if ((lastcpi = classpath_entries)) {
486 while (lastcpi->next)
487 lastcpi = lastcpi->next;
490 for (start = classpath; (*start) != '\0';) {
492 /* search for ':' delimiter to get the end of the current entry */
493 for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
497 filenamelen = end - start;
499 if (filenamelen > 3) {
500 if (strncasecmp(end - 3, "zip", 3) == 0 ||
501 strncasecmp(end - 3, "jar", 3) == 0) {
506 /* save classpath entries as absolute pathnames */
511 if (*start != '/') { /* XXX fix me for win32 */
513 cwdlen = strlen(cwd) + strlen("/");
516 /* allocate memory for filename and fill it */
518 filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
522 strcpy(filename, cwd);
523 strcat(filename, "/");
524 strncat(filename, start, filenamelen);
526 /* add cwd length to file length */
527 filenamelen += cwdlen;
530 strncpy(filename, start, filenamelen);
531 filename[filenamelen] = '\0';
537 #if defined(USE_ZLIB)
538 unzFile uf = unzOpen(filename);
541 cpi = NEW(classpath_info);
542 cpi->type = CLASSPATH_ARCHIVE;
545 cpi->path = filename;
546 cpi->pathlen = filenamelen;
550 throw_cacao_exception_exit(string_java_lang_InternalError,
551 "zip/jar files not supported");
555 cpi = NEW(classpath_info);
556 cpi->type = CLASSPATH_PATH;
559 if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
560 filename[filenamelen] = '/';
561 filename[filenamelen + 1] = '\0';
565 cpi->path = filename;
566 cpi->pathlen = filenamelen;
569 /* attach current classpath entry */
572 if (!classpath_entries)
573 classpath_entries = cpi;
581 /* goto next classpath entry, skip ':' delimiter */
593 void create_all_classes()
597 for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
598 #if defined(USE_ZLIB)
599 if (cpi->type == CLASSPATH_ARCHIVE) {
603 s = (unz_s *) cpi->uf;
604 ce = s->cacao_dir_list;
607 (void) class_new(ce->name);
613 #if defined(USE_ZLIB)
620 /* suck_start ******************************************************************
622 Returns true if classbuffer is already loaded or a file for the
623 specified class has succussfully been read in. All directories of
624 the searchpath are used to find the classfile (<classname>.class).
625 Returns false if no classfile is found and writes an error message.
627 *******************************************************************************/
629 classbuffer *suck_start(classinfo *c)
641 /* initialize return value */
646 filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
647 filename = MNEW(char, filenamelen);
649 utf_sprint(filename, c->name);
650 strcat(filename, ".class");
652 /* walk through all classpath entries */
654 for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
655 #if defined(USE_ZLIB)
656 if (cpi->type == CLASSPATH_ARCHIVE) {
658 #if defined(USE_THREADS)
659 /* enter a monitor on zip/jar archives */
661 builtin_monitorenter((java_objectheader *) cpi);
664 if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
665 unz_file_info file_info;
667 if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
668 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
669 if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
670 cb = NEW(classbuffer);
672 cb->size = file_info.uncompressed_size;
673 cb->data = MNEW(u1, cb->size);
674 cb->pos = cb->data - 1;
676 len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
678 if (len != cb->size) {
680 log_text("Error while unzipping");
687 log_text("Error while opening file in archive");
691 log_text("Error while retrieving fileinfo");
694 unzCloseCurrentFile(cpi->uf);
696 #if defined(USE_THREADS)
697 /* leave the monitor */
699 builtin_monitorexit((java_objectheader *) cpi);
703 #endif /* defined(USE_ZLIB) */
705 path = MNEW(char, cpi->pathlen + filenamelen);
706 strcpy(path, cpi->path);
707 strcat(path, filename);
709 classfile = fopen(path, "r");
711 if (classfile) { /* file exists */
712 if (!stat(path, &buffer)) { /* read classfile data */
713 cb = NEW(classbuffer);
715 cb->size = buffer.st_size;
716 cb->data = MNEW(u1, cb->size);
717 cb->pos = cb->data - 1;
719 /* read class data */
720 len = fread(cb->data, 1, cb->size, classfile);
722 if (len != buffer.st_size) {
724 /* if (ferror(classfile)) { */
733 MFREE(path, char, cpi->pathlen + filenamelen);
734 #if defined(USE_ZLIB)
741 dolog("Warning: Can not open class file '%s'", filename);
743 MFREE(filename, char, filenamelen);
749 /************************** function suck_stop *********************************
751 frees memory for buffer with classfile data.
752 Caution: this function may only be called if buffer has been allocated
753 by suck_start with reading a file
755 *******************************************************************************/
757 void suck_stop(classbuffer *cb)
761 MFREE(cb->data, u1, cb->size);
762 FREE(cb, classbuffer);
766 /******************************************************************************/
767 /******************* Some support functions ***********************************/
768 /******************************************************************************/
770 void fprintflags (FILE *fp, u2 f)
772 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
773 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
774 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
775 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
776 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
777 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
778 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
779 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
780 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
781 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
782 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
786 /********** internal function: printflags (only for debugging) ***************/
788 void printflags(u2 f)
790 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
791 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
792 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
793 if ( f & ACC_STATIC ) printf (" STATIC");
794 if ( f & ACC_FINAL ) printf (" FINAL");
795 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
796 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
797 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
798 if ( f & ACC_NATIVE ) printf (" NATIVE");
799 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
800 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
804 /********************** Function: skipattributebody ****************************
806 skips an attribute after the 16 bit reference to attribute_name has already
809 *******************************************************************************/
811 static bool skipattributebody(classbuffer *cb)
815 if (!check_classbuffer_size(cb, 4))
820 if (!check_classbuffer_size(cb, len))
823 skip_nbytes(cb, len);
829 /************************* Function: skipattributes ****************************
831 skips num attribute structures
833 *******************************************************************************/
835 static bool skipattributes(classbuffer *cb, u4 num)
840 for (i = 0; i < num; i++) {
841 if (!check_classbuffer_size(cb, 2 + 4))
847 if (!check_classbuffer_size(cb, len))
850 skip_nbytes(cb, len);
857 /******************** function:: class_getconstant *****************************
859 retrieves the value at position 'pos' of the constantpool of a class
860 if the type of the value is other than 'ctype' the system is stopped
862 *******************************************************************************/
864 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
866 /* check index and type of constantpool entry */
867 /* (pos == 0 is caught by type comparison) */
868 if (pos >= c->cpcount || c->cptags[pos] != ctype) {
869 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
873 return c->cpinfos[pos];
877 /******************** function: innerclass_getconstant ************************
879 like class_getconstant, but if cptags is ZERO null is returned
881 *******************************************************************************/
883 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
885 /* invalid position in constantpool */
886 if (pos >= c->cpcount) {
887 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
891 /* constantpool entry of type 0 */
895 /* check type of constantpool entry */
896 if (c->cptags[pos] != ctype) {
897 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
901 return c->cpinfos[pos];
905 /********************* Function: class_constanttype ****************************
907 Determines the type of a class entry in the ConstantPool
909 *******************************************************************************/
911 u4 class_constanttype(classinfo *c, u4 pos)
913 if (pos <= 0 || pos >= c->cpcount) {
914 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
918 return c->cptags[pos];
922 /* load_constantpool ***********************************************************
924 Loads the constantpool of a class, the entries are transformed into
925 a simpler format by resolving references (a detailed overview of
926 the compact structures can be found in global.h).
928 *******************************************************************************/
930 static bool load_constantpool(classbuffer *cb)
933 /* The following structures are used to save information which cannot be
934 processed during the first pass. After the complete constantpool has
935 been traversed the references can be resolved.
936 (only in specific order) */
938 /* CONSTANT_Class entries */
939 typedef struct forward_class {
940 struct forward_class *next;
945 /* CONSTANT_String */
946 typedef struct forward_string {
947 struct forward_string *next;
952 /* CONSTANT_NameAndType */
953 typedef struct forward_nameandtype {
954 struct forward_nameandtype *next;
958 } forward_nameandtype;
960 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
961 typedef struct forward_fieldmethint {
962 struct forward_fieldmethint *next;
966 u2 nameandtype_index;
967 } forward_fieldmethint;
973 forward_class *forward_classes = NULL;
974 forward_string *forward_strings = NULL;
975 forward_nameandtype *forward_nameandtypes = NULL;
976 forward_fieldmethint *forward_fieldmethints = NULL;
980 forward_nameandtype *nfn;
981 forward_fieldmethint *nff;
989 /* number of entries in the constant_pool table plus one */
990 if (!check_classbuffer_size(cb, 2))
993 cpcount = c->cpcount = suck_u2(cb);
995 /* allocate memory */
996 cptags = c->cptags = MNEW(u1, cpcount);
997 cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1000 *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
1004 #if defined(STATISTICS)
1006 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1009 /* initialize constantpool */
1010 for (idx = 0; idx < cpcount; idx++) {
1011 cptags[idx] = CONSTANT_UNUSED;
1012 cpinfos[idx] = NULL;
1016 /******* first pass *******/
1017 /* entries which cannot be resolved now are written into
1018 temporary structures and traversed again later */
1021 while (idx < cpcount) {
1024 /* get constant type */
1025 if (!check_classbuffer_size(cb, 1))
1031 case CONSTANT_Class:
1032 nfc = NEW(forward_class);
1034 nfc->next = forward_classes;
1035 forward_classes = nfc;
1037 nfc->thisindex = idx;
1038 /* reference to CONSTANT_NameAndType */
1039 if (!check_classbuffer_size(cb, 2))
1042 nfc->name_index = suck_u2(cb);
1047 case CONSTANT_String:
1048 nfs = NEW(forward_string);
1050 nfs->next = forward_strings;
1051 forward_strings = nfs;
1053 nfs->thisindex = idx;
1055 /* reference to CONSTANT_Utf8_info with string characters */
1056 if (!check_classbuffer_size(cb, 2))
1059 nfs->string_index = suck_u2(cb);
1064 case CONSTANT_NameAndType:
1065 nfn = NEW(forward_nameandtype);
1067 nfn->next = forward_nameandtypes;
1068 forward_nameandtypes = nfn;
1070 nfn->thisindex = idx;
1072 if (!check_classbuffer_size(cb, 2 + 2))
1075 /* reference to CONSTANT_Utf8_info containing simple name */
1076 nfn->name_index = suck_u2(cb);
1078 /* reference to CONSTANT_Utf8_info containing field or method
1080 nfn->sig_index = suck_u2(cb);
1085 case CONSTANT_Fieldref:
1086 case CONSTANT_Methodref:
1087 case CONSTANT_InterfaceMethodref:
1088 nff = NEW(forward_fieldmethint);
1090 nff->next = forward_fieldmethints;
1091 forward_fieldmethints = nff;
1093 nff->thisindex = idx;
1097 if (!check_classbuffer_size(cb, 2 + 2))
1100 /* class or interface type that contains the declaration of the
1102 nff->class_index = suck_u2(cb);
1104 /* name and descriptor of the field or method */
1105 nff->nameandtype_index = suck_u2(cb);
1110 case CONSTANT_Integer: {
1111 constant_integer *ci = NEW(constant_integer);
1113 #if defined(STATISTICS)
1115 count_const_pool_len += sizeof(constant_integer);
1118 if (!check_classbuffer_size(cb, 4))
1121 ci->value = suck_s4(cb);
1122 cptags[idx] = CONSTANT_Integer;
1129 case CONSTANT_Float: {
1130 constant_float *cf = NEW(constant_float);
1132 #if defined(STATISTICS)
1134 count_const_pool_len += sizeof(constant_float);
1137 if (!check_classbuffer_size(cb, 4))
1140 cf->value = suck_float(cb);
1141 cptags[idx] = CONSTANT_Float;
1148 case CONSTANT_Long: {
1149 constant_long *cl = NEW(constant_long);
1151 #if defined(STATISTICS)
1153 count_const_pool_len += sizeof(constant_long);
1156 if (!check_classbuffer_size(cb, 8))
1159 cl->value = suck_s8(cb);
1160 cptags[idx] = CONSTANT_Long;
1163 if (idx > cpcount) {
1165 new_classformaterror(c, "Invalid constant pool entry");
1171 case CONSTANT_Double: {
1172 constant_double *cd = NEW(constant_double);
1174 #if defined(STATISTICS)
1176 count_const_pool_len += sizeof(constant_double);
1179 if (!check_classbuffer_size(cb, 8))
1182 cd->value = suck_double(cb);
1183 cptags[idx] = CONSTANT_Double;
1186 if (idx > cpcount) {
1188 new_classformaterror(c, "Invalid constant pool entry");
1194 case CONSTANT_Utf8: {
1197 /* number of bytes in the bytes array (not string-length) */
1198 if (!check_classbuffer_size(cb, 2))
1201 length = suck_u2(cb);
1202 cptags[idx] = CONSTANT_Utf8;
1204 /* validate the string */
1205 if (!check_classbuffer_size(cb, length))
1209 !is_valid_utf((char *) (cb->pos + 1),
1210 (char *) (cb->pos + 1 + length))) {
1211 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1212 panic("Invalid UTF-8 string");
1214 /* insert utf-string into the utf-symboltable */
1215 cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
1217 /* skip bytes of the string (buffer size check above) */
1218 skip_nbytes(cb, length);
1225 new_classformaterror(c, "Illegal constant pool type");
1231 /* resolve entries in temporary structures */
1233 while (forward_classes) {
1235 class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1237 if (opt_verify && !is_valid_name_utf(name))
1238 panic("Class reference with invalid name");
1240 cptags[forward_classes->thisindex] = CONSTANT_Class;
1241 /* retrieve class from class-table */
1244 tc = class_new_intern(name);
1246 if (!load_class_from_classloader(tc, c->classloader))
1249 /* link the class later, because we cannot link the class currently
1251 list_addfirst(&unlinkedclasses, tc);
1253 cpinfos[forward_classes->thisindex] = tc;
1256 cpinfos[forward_classes->thisindex] = class_new(name);
1259 nfc = forward_classes;
1260 forward_classes = forward_classes->next;
1261 FREE(nfc, forward_class);
1264 while (forward_strings) {
1266 class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1268 /* resolve utf-string */
1269 cptags[forward_strings->thisindex] = CONSTANT_String;
1270 cpinfos[forward_strings->thisindex] = text;
1272 nfs = forward_strings;
1273 forward_strings = forward_strings->next;
1274 FREE(nfs, forward_string);
1277 while (forward_nameandtypes) {
1278 constant_nameandtype *cn = NEW(constant_nameandtype);
1280 #if defined(STATISTICS)
1282 count_const_pool_len += sizeof(constant_nameandtype);
1285 /* resolve simple name and descriptor */
1286 cn->name = class_getconstant(c,
1287 forward_nameandtypes->name_index,
1290 cn->descriptor = class_getconstant(c,
1291 forward_nameandtypes->sig_index,
1296 if (!is_valid_name_utf(cn->name)) {
1298 new_classformaterror(c,
1299 "Illegal Field name \"%s\"",
1305 /* disallow referencing <clinit> among others */
1306 if (cn->name->text[0] == '<' && cn->name != utf_init) {
1308 new_exception_utfmessage(string_java_lang_InternalError,
1314 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1315 cpinfos[forward_nameandtypes->thisindex] = cn;
1317 nfn = forward_nameandtypes;
1318 forward_nameandtypes = forward_nameandtypes->next;
1319 FREE(nfn, forward_nameandtype);
1322 while (forward_fieldmethints) {
1323 constant_nameandtype *nat;
1324 constant_FMIref *fmi = NEW(constant_FMIref);
1326 #if defined(STATISTICS)
1328 count_const_pool_len += sizeof(constant_FMIref);
1330 /* resolve simple name and descriptor */
1331 nat = class_getconstant(c,
1332 forward_fieldmethints->nameandtype_index,
1333 CONSTANT_NameAndType);
1335 fmi->class = class_getconstant(c,
1336 forward_fieldmethints->class_index,
1338 fmi->name = nat->name;
1339 fmi->descriptor = nat->descriptor;
1341 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1342 cpinfos[forward_fieldmethints->thisindex] = fmi;
1344 switch (forward_fieldmethints->tag) {
1345 case CONSTANT_Fieldref: /* check validity of descriptor */
1346 checkfielddescriptor(fmi->descriptor->text,
1347 utf_end(fmi->descriptor));
1349 case CONSTANT_InterfaceMethodref:
1350 case CONSTANT_Methodref: /* check validity of descriptor */
1351 checkmethoddescriptor(c, fmi->descriptor);
1355 nff = forward_fieldmethints;
1356 forward_fieldmethints = forward_fieldmethints->next;
1357 FREE(nff, forward_fieldmethint);
1360 /* everything was ok */
1366 /* load_field ******************************************************************
1368 Load everything about a class field from the class file and fill a
1369 'fieldinfo' structure. For static fields, space in the data segment
1372 *******************************************************************************/
1374 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
1376 static bool load_field(classbuffer *cb, fieldinfo *f)
1381 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
1386 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1389 f->flags = suck_u2(cb);
1391 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1395 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1401 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1402 *exceptionptr = new_classformaterror(c,
1403 "Illegal Field name \"%s\"",
1408 /* check flag consistency */
1409 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1411 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1412 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1414 new_classformaterror(c,
1415 "Illegal field modifiers: 0x%X",
1420 if (c->flags & ACC_INTERFACE) {
1421 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1422 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1423 f->flags & ACC_TRANSIENT) {
1425 new_classformaterror(c,
1426 "Illegal field modifiers: 0x%X",
1432 /* check descriptor */
1433 checkfielddescriptor(f->descriptor->text, utf_end(f->descriptor));
1436 f->type = jtype = desc_to_type(f->descriptor); /* data type */
1437 f->offset = 0; /* offset from start of object */
1442 case TYPE_INT: f->value.i = 0; break;
1443 case TYPE_FLOAT: f->value.f = 0.0; break;
1444 case TYPE_DOUBLE: f->value.d = 0.0; break;
1445 case TYPE_ADDRESS: f->value.a = NULL; break;
1448 f->value.l = 0; break;
1450 f->value.l.low = 0; f->value.l.high = 0; break;
1454 /* read attributes */
1455 if (!check_classbuffer_size(cb, 2))
1458 attrnum = suck_u2(cb);
1459 for (i = 0; i < attrnum; i++) {
1460 if (!check_classbuffer_size(cb, 2))
1463 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1466 if (u == utf_ConstantValue) {
1467 if (!check_classbuffer_size(cb, 4 + 2))
1470 /* check attribute length */
1471 if (suck_u4(cb) != 2) {
1473 new_classformaterror(c, "Wrong size for VALUE attribute");
1477 /* constant value attribute */
1478 if (pindex != field_load_NOVALUE) {
1480 new_classformaterror(c,
1481 "Multiple ConstantValue attributes");
1485 /* index of value in constantpool */
1486 pindex = suck_u2(cb);
1488 /* initialize field with value from constantpool */
1491 constant_integer *ci;
1493 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1496 f->value.i = ci->value;
1503 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1506 f->value.l = cl->value;
1513 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1516 f->value.f = cf->value;
1521 constant_double *cd;
1523 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1526 f->value.d = cd->value;
1531 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1534 /* create javastring from compressed utf8-string */
1535 f->value.a = literalstring_new(u);
1539 log_text("Invalid Constant - Type");
1543 /* unknown attribute */
1544 if (!skipattributebody(cb))
1549 /* everything was ok */
1555 /* load_method *****************************************************************
1557 Loads a method from the class file and fills an existing
1558 'methodinfo' structure. For native methods, the function pointer
1559 field is set to the real function pointer, for JavaVM methods a
1560 pointer to the compiler is used preliminarily.
1562 *******************************************************************************/
1564 static bool load_method(classbuffer *cb, methodinfo *m)
1575 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1576 initObjectLock(&m->header);
1581 count_all_methods++;
1584 m->thrownexceptionscount = 0;
1585 m->linenumbercount = 0;
1588 m->nativelyoverloaded = false;
1590 if (!check_classbuffer_size(cb, 2 + 2 + 2))
1593 m->flags = suck_u2(cb);
1595 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1599 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1604 if (!is_valid_name_utf(m->name))
1605 panic("Method with invalid name");
1607 if (m->name->text[0] == '<'
1608 && m->name != utf_init && m->name != utf_clinit)
1609 panic("Method with invalid special name");
1612 argcount = checkmethoddescriptor(c, m->descriptor);
1614 if (!(m->flags & ACC_STATIC))
1615 argcount++; /* count the 'this' argument */
1618 if (argcount > 255) {
1620 new_classformaterror(c, "Too many arguments in signature");
1624 /* check flag consistency */
1625 if (m->name != utf_clinit) {
1626 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1628 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1630 new_classformaterror(c,
1631 "Illegal method modifiers: 0x%X",
1636 if (m->flags & ACC_ABSTRACT) {
1637 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1638 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1640 new_classformaterror(c,
1641 "Illegal method modifiers: 0x%X",
1647 if (c->flags & ACC_INTERFACE) {
1648 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1650 new_classformaterror(c,
1651 "Illegal method modifiers: 0x%X",
1657 if (m->name == utf_init) {
1658 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1659 ACC_NATIVE | ACC_ABSTRACT))
1660 panic("Instance initialization method has invalid flags set");
1666 m->basicblockcount = 0;
1667 m->basicblocks = NULL;
1668 m->basicblockindex = NULL;
1669 m->instructioncount = 0;
1670 m->instructions = NULL;
1673 m->exceptiontable = NULL;
1674 m->stubroutine = NULL;
1676 m->entrypoint = NULL;
1677 m->methodUsed = NOTUSED;
1680 m->subRedefsUsed = 0;
1684 if (!check_classbuffer_size(cb, 2))
1687 attrnum = suck_u2(cb);
1688 for (i = 0; i < attrnum; i++) {
1691 if (!check_classbuffer_size(cb, 2))
1694 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1697 if (aname == utf_Code) {
1698 if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1700 new_classformaterror(c,
1701 "Code attribute in native or abstract methods");
1708 new_classformaterror(c, "Multiple Code attributes");
1713 if (!check_classbuffer_size(cb, 4 + 2 + 2))
1717 m->maxstack = suck_u2(cb);
1718 m->maxlocals = suck_u2(cb);
1720 if (m->maxlocals < argcount) {
1722 new_classformaterror(c, "Arguments can't fit into locals");
1727 if (!check_classbuffer_size(cb, 4))
1730 m->jcodelength = suck_u4(cb);
1732 if (m->jcodelength == 0) {
1734 new_classformaterror(c, "Code of a method has length 0");
1739 if (m->jcodelength > 65535) {
1741 new_classformaterror(c,
1742 "Code of a method longer than 65535 bytes");
1747 if (!check_classbuffer_size(cb, m->jcodelength))
1750 m->jcode = MNEW(u1, m->jcodelength);
1751 suck_nbytes(m->jcode, cb, m->jcodelength);
1753 if (!check_classbuffer_size(cb, 2))
1756 m->exceptiontablelength = suck_u2(cb);
1757 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1760 m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1762 #if defined(STATISTICS)
1764 count_vmcode_len += m->jcodelength + 18;
1765 count_extable_len += 8 * m->exceptiontablelength;
1769 for (j = 0; j < m->exceptiontablelength; j++) {
1771 m->exceptiontable[j].startpc = suck_u2(cb);
1772 m->exceptiontable[j].endpc = suck_u2(cb);
1773 m->exceptiontable[j].handlerpc = suck_u2(cb);
1777 m->exceptiontable[j].catchtype = NULL;
1780 if (!(m->exceptiontable[j].catchtype =
1781 class_getconstant(c, idx, CONSTANT_Class)))
1786 if (!check_classbuffer_size(cb, 2))
1789 codeattrnum = suck_u2(cb);
1791 for (; codeattrnum > 0; codeattrnum--) {
1794 if (!check_classbuffer_size(cb, 2))
1797 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1800 if (caname == utf_LineNumberTable) {
1803 if (!check_classbuffer_size(cb, 4 + 2))
1807 m->linenumbercount = suck_u2(cb);
1809 if (!check_classbuffer_size(cb,
1810 (2 + 2) * m->linenumbercount))
1813 m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1815 for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1816 m->linenumbers[lncid].start_pc = suck_u2(cb);
1817 m->linenumbers[lncid].line_number = suck_u2(cb);
1821 if (!skipattributes(cb, codeattrnum))
1827 if (!skipattributebody(cb))
1832 } else if (aname == utf_Exceptions) {
1835 if (m->thrownexceptions) {
1837 new_classformaterror(c, "Multiple Exceptions attributes");
1841 if (!check_classbuffer_size(cb, 4 + 2))
1844 suck_u4(cb); /* length */
1845 m->thrownexceptionscount = suck_u2(cb);
1847 if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1850 m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
1852 for (j = 0; j < m->thrownexceptionscount; j++) {
1853 if (!((m->thrownexceptions)[j] =
1854 class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1859 if (!skipattributebody(cb))
1864 if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1865 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1870 /* everything was ok */
1876 /* load_attribute **************************************************************
1878 Read attributes from classfile.
1880 *******************************************************************************/
1882 static bool load_attributes(classbuffer *cb, u4 num)
1890 for (i = 0; i < num; i++) {
1891 /* retrieve attribute name */
1892 if (!check_classbuffer_size(cb, 2))
1895 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1898 if (aname == utf_InnerClasses) {
1899 /* innerclasses attribute */
1900 if (c->innerclass) {
1902 new_classformaterror(c, "Multiple InnerClasses attributes");
1906 if (!check_classbuffer_size(cb, 4 + 2))
1909 /* skip attribute length */
1912 /* number of records */
1913 c->innerclasscount = suck_u2(cb);
1915 if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1918 /* allocate memory for innerclass structure */
1919 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1921 for (j = 0; j < c->innerclasscount; j++) {
1922 /* The innerclass structure contains a class with an encoded
1923 name, its defining scope, its simple name and a bitmask of
1924 the access flags. If an inner class is not a member, its
1925 outer_class is NULL, if a class is anonymous, its name is
1928 innerclassinfo *info = c->innerclass + j;
1931 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1933 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1935 innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1936 info->flags = suck_u2(cb);
1939 } else if (aname == utf_SourceFile) {
1940 if (!check_classbuffer_size(cb, 4 + 2))
1943 if (suck_u4(cb) != 2) {
1945 new_classformaterror(c, "Wrong size for VALUE attribute");
1949 if (c->sourcefile) {
1951 new_classformaterror(c, "Multiple SourceFile attributes");
1955 if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1959 /* unknown attribute */
1960 if (!skipattributebody(cb))
1969 /***************** Function: print_arraydescriptor ****************************
1971 Debugging helper for displaying an arraydescriptor
1973 *******************************************************************************/
1975 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
1978 fprintf(file, "<NULL>");
1983 if (desc->componentvftbl) {
1984 if (desc->componentvftbl->class)
1985 utf_fprint(file, desc->componentvftbl->class->name);
1987 fprintf(file, "<no classinfo>");
1993 if (desc->elementvftbl) {
1994 if (desc->elementvftbl->class)
1995 utf_fprint(file, desc->elementvftbl->class->name);
1997 fprintf(file, "<no classinfo>");
2001 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
2002 desc->dataoffset, desc->componentsize);
2006 /* load_class_from_classloader *************************************************
2010 *******************************************************************************/
2012 classinfo *load_class_from_classloader(classinfo *c, java_objectheader *cl)
2016 /* if other class loader than bootstrap, call it */
2021 lc = class_resolveclassmethod(cl->vftbl->class,
2023 utf_java_lang_String__java_lang_Class,
2024 class_java_lang_Object,
2030 r = (classinfo *) asm_calljavafunction(lc,
2032 javastring_new(c->name),
2038 return load_class_bootstrap(c);
2043 /* load_class_bootstrap ********************************************************
2047 *******************************************************************************/
2049 classinfo *load_class_bootstrap(classinfo *c)
2054 #if defined(USE_THREADS)
2055 /* enter a monitor on the class */
2057 builtin_monitorenter((java_objectheader *) c);
2060 /* maybe the class is already loaded */
2063 #if defined(USE_THREADS)
2064 builtin_monitorexit((java_objectheader *) c);
2070 #if defined(STATISTICS)
2073 if (getcompilingtime)
2074 compilingtime_stop();
2077 loadingtime_start();
2080 /* load classdata, throw exception on error */
2082 if ((cb = suck_start(c)) == NULL) {
2083 /* this means, the classpath was not set properly */
2084 if (c->name == utf_java_lang_Object)
2085 throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2086 "java/lang/Object");
2089 new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2092 #if defined(USE_THREADS)
2093 builtin_monitorexit((java_objectheader *) c);
2099 /* load the class from the buffer */
2101 r = load_class_from_classbuffer(cb);
2103 /* if return value is NULL, we had a problem and the class is not loaded */
2107 /* now free the allocated memory, otherwise we could ran into a DOS */
2114 #if defined(STATISTICS)
2120 if (getcompilingtime)
2121 compilingtime_start();
2124 #if defined(USE_THREADS)
2125 /* leave the monitor */
2127 builtin_monitorexit((java_objectheader *) c);
2134 /* load_class_from_classbuffer *************************************************
2136 Loads everything interesting about a class from the class file. The
2137 'classinfo' structure must have been allocated previously.
2139 The super class and the interfaces implemented by this class need
2140 not be loaded. The link is set later by the function 'class_link'.
2142 The loaded class is removed from the list 'unloadedclasses' and
2143 added to the list 'unlinkedclasses'.
2145 *******************************************************************************/
2147 classinfo *load_class_from_classbuffer(classbuffer *cb)
2153 char msg[MAXLOGTEXT]; /* maybe we get an exception */
2155 /* get the classbuffer's class */
2158 /* maybe the class is already loaded */
2162 #if defined(STATISTICS)
2164 count_class_loads++;
2167 /* output for debugging purposes */
2169 log_message_class("Loading class: ", c);
2171 /* class is somewhat loaded */
2174 if (!check_classbuffer_size(cb, 4 + 2 + 2))
2177 /* check signature */
2178 if (suck_u4(cb) != MAGIC) {
2179 *exceptionptr = new_classformaterror(c, "Bad magic number");
2188 if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2190 new_unsupportedclassversionerror(c,
2191 "Unsupported major.minor version %d.%d",
2197 /* load the constant pool */
2198 if (!load_constantpool(cb))
2202 c->erroneous_state = 0;
2203 c->initializing_thread = 0;
2205 c->classUsed = NOTUSED; /* not used initially CO-RT */
2209 if (!check_classbuffer_size(cb, 2))
2212 c->flags = suck_u2(cb);
2213 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
2215 /* check ACC flags consistency */
2216 if (c->flags & ACC_INTERFACE) {
2217 if (!(c->flags & ACC_ABSTRACT)) {
2218 /* We work around this because interfaces in JDK 1.1 are
2219 * not declared abstract. */
2221 c->flags |= ACC_ABSTRACT;
2222 /* panic("Interface class not declared abstract"); */
2225 if (c->flags & ACC_FINAL) {
2227 new_classformaterror(c,
2228 "Illegal class modifiers: 0x%X", c->flags);
2233 if (c->flags & ACC_SUPER) {
2234 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2238 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2240 new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2245 if (!check_classbuffer_size(cb, 2 + 2))
2250 if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
2254 utf_sprint(msg, c->name);
2255 sprintf(msg + strlen(msg), " (wrong name: ");
2256 utf_sprint(msg + strlen(msg), tc->name);
2257 sprintf(msg + strlen(msg), ")");
2260 new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2265 /* retrieve superclass */
2266 if ((i = suck_u2(cb))) {
2267 if (!(c->super = class_getconstant(c, i, CONSTANT_Class)))
2270 /* java.lang.Object may not have a super class. */
2271 if (c->name == utf_java_lang_Object) {
2273 new_exception_message(string_java_lang_ClassFormatError,
2274 "java.lang.Object with superclass");
2279 /* Interfaces must have java.lang.Object as super class. */
2280 if ((c->flags & ACC_INTERFACE) &&
2281 c->super->name != utf_java_lang_Object) {
2283 new_exception_message(string_java_lang_ClassFormatError,
2284 "Interfaces must have java.lang.Object as superclass");
2292 /* This is only allowed for java.lang.Object. */
2293 if (c->name != utf_java_lang_Object) {
2294 *exceptionptr = new_classformaterror(c, "Bad superclass index");
2300 /* retrieve interfaces */
2301 if (!check_classbuffer_size(cb, 2))
2304 c->interfacescount = suck_u2(cb);
2306 if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2309 c->interfaces = MNEW(classinfo*, c->interfacescount);
2310 for (i = 0; i < c->interfacescount; i++) {
2311 if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2316 if (!check_classbuffer_size(cb, 2))
2319 c->fieldscount = suck_u2(cb);
2320 c->fields = GCNEW(fieldinfo, c->fieldscount);
2321 /* c->fields = MNEW(fieldinfo, c->fieldscount); */
2322 for (i = 0; i < c->fieldscount; i++) {
2323 if (!load_field(cb, &(c->fields[i])))
2328 if (!check_classbuffer_size(cb, 2))
2331 c->methodscount = suck_u2(cb);
2332 /* c->methods = GCNEW(methodinfo, c->methodscount); */
2333 c->methods = MNEW(methodinfo, c->methodscount);
2334 for (i = 0; i < c->methodscount; i++) {
2335 if (!load_method(cb, &(c->methods[i])))
2339 /* Check if all fields and methods can be uniquely
2340 * identified by (name,descriptor). */
2342 /* We use a hash table here to avoid making the
2343 * average case quadratic in # of methods, fields.
2345 static int shift = 0;
2347 u2 *next; /* for chaining colliding hash entries */
2353 /* Allocate hashtable */
2354 len = c->methodscount;
2355 if (len < c->fieldscount) len = c->fieldscount;
2357 hashtab = MNEW(u2,(hashlen + len));
2358 next = hashtab + hashlen;
2360 /* Determine bitshift (to get good hash values) */
2370 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2372 for (i = 0; i < c->fieldscount; ++i) {
2373 fieldinfo *fi = c->fields + i;
2375 /* It's ok if we lose bits here */
2376 index = ((((size_t) fi->name) +
2377 ((size_t) fi->descriptor)) >> shift) % hashlen;
2379 if ((old = hashtab[index])) {
2383 if (c->fields[old].name == fi->name &&
2384 c->fields[old].descriptor == fi->descriptor) {
2386 new_classformaterror(c,
2387 "Repetitive field name/signature");
2391 } while ((old = next[old]));
2393 hashtab[index] = i + 1;
2397 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2399 for (i = 0; i < c->methodscount; ++i) {
2400 methodinfo *mi = c->methods + i;
2402 /* It's ok if we lose bits here */
2403 index = ((((size_t) mi->name) +
2404 ((size_t) mi->descriptor)) >> shift) % hashlen;
2408 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2409 printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2413 if ((old = hashtab[index])) {
2417 if (c->methods[old].name == mi->name &&
2418 c->methods[old].descriptor == mi->descriptor) {
2420 new_classformaterror(c,
2421 "Repetitive method name/signature");
2425 } while ((old = next[old]));
2427 hashtab[index] = i + 1;
2430 MFREE(hashtab, u2, (hashlen + len));
2433 #if defined(STATISTICS)
2435 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2436 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2437 count_class_infos += sizeof(methodinfo) * c->methodscount;
2441 /* load attribute structures */
2442 if (!check_classbuffer_size(cb, 2))
2445 if (!load_attributes(cb, suck_u2(cb)))
2449 /* Pre java 1.5 version don't check this. This implementation is like
2450 java 1.5 do it: for class file version 45.3 we don't check it, older
2451 versions are checked.
2453 if ((ma == 45 && mi > 3) || ma > 45) {
2454 /* check if all data has been read */
2455 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2457 if (classdata_left > 0) {
2459 new_classformaterror(c, "Extra bytes at the end of class file");
2466 log_message_class("Loading done class: ", c);
2473 /******************* Function: class_new_array *********************************
2475 This function is called by class_new to setup an array class.
2477 *******************************************************************************/
2479 void class_new_array(classinfo *c)
2481 classinfo *comp = NULL;
2485 /* Check array class name */
2486 namelen = c->name->blength;
2487 if (namelen < 2 || c->name->text[0] != '[')
2488 panic("Invalid array class name");
2490 /* Check the component type */
2491 switch (c->name->text[1]) {
2493 /* c is an array of arrays. We have to create the component class. */
2495 comp = class_new_intern(utf_new_intern(c->name->text + 1,
2497 load_class_from_classloader(comp, c->classloader);
2498 list_addfirst(&unlinkedclasses, comp);
2501 comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2506 /* c is an array of objects. */
2507 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2508 panic("Invalid array class name");
2511 comp = class_new_intern(utf_new_intern(c->name->text + 2,
2513 load_class_from_classloader(comp, c->classloader);
2514 list_addfirst(&unlinkedclasses, comp);
2517 comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2522 /* Setup the array class */
2523 c->super = class_java_lang_Object;
2524 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2526 c->interfacescount = 2;
2527 c->interfaces = MNEW(classinfo*, 2);
2532 tc = class_java_lang_Cloneable;
2533 load_class_bootstrap(tc);
2534 list_addfirst(&unlinkedclasses, tc);
2535 c->interfaces[0] = tc;
2537 tc = class_java_io_Serializable;
2538 load_class_bootstrap(tc);
2539 list_addfirst(&unlinkedclasses, tc);
2540 c->interfaces[1] = tc;
2543 c->interfaces[0] = class_java_lang_Cloneable;
2544 c->interfaces[1] = class_java_io_Serializable;
2547 c->methodscount = 1;
2548 c->methods = MNEW(methodinfo, c->methodscount);
2551 MSET(clone, 0, methodinfo, 1);
2552 clone->flags = ACC_PUBLIC;
2553 clone->name = utf_new_char("clone");
2554 clone->descriptor = utf_void__java_lang_Object;
2556 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2557 clone->monoPoly = MONO;
2559 /* XXX: field: length? */
2561 /* array classes are not loaded from class files */
2566 /************************* Function: class_findfield ***************************
2568 Searches a 'classinfo' structure for a field having the given name and
2571 *******************************************************************************/
2573 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2577 for (i = 0; i < c->fieldscount; i++) {
2578 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2579 return &(c->fields[i]);
2582 panic("Can not find field given in CONSTANT_Fieldref");
2584 /* keep compiler happy */
2589 /****************** Function: class_resolvefield_int ***************************
2591 This is an internally used helper function. Do not use this directly.
2593 Tries to resolve a field having the given name and type.
2594 If the field cannot be resolved, NULL is returned.
2596 *******************************************************************************/
2598 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2603 /* search for field in class c */
2605 for (i = 0; i < c->fieldscount; i++) {
2606 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2607 return &(c->fields[i]);
2611 /* try superinterfaces recursively */
2613 for (i = 0; i < c->interfacescount; i++) {
2614 fi = class_resolvefield_int(c->interfaces[i], name, desc);
2619 /* try superclass */
2622 return class_resolvefield_int(c->super, name, desc);
2630 /********************* Function: class_resolvefield ***************************
2632 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2634 If the field cannot be resolved the return value is NULL. If EXCEPT is
2635 true *exceptionptr is set, too.
2637 *******************************************************************************/
2639 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2640 classinfo *referer, bool except)
2644 /* XXX resolve class c */
2645 /* XXX check access from REFERER to C */
2647 fi = class_resolvefield_int(c, name, desc);
2652 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2658 /* XXX check access rights */
2664 /* class_findmethod ************************************************************
2666 Searches a 'classinfo' structure for a method having the given name
2667 and descriptor. If descriptor is NULL, it is ignored.
2669 *******************************************************************************/
2671 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2676 for (i = 0; i < c->methodscount; i++) {
2677 m = &(c->methods[i]);
2679 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
2687 /*********************** Function: class_fetchmethod **************************
2689 like class_findmethod, but aborts with an error if the method is not found
2691 *******************************************************************************/
2693 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2697 mi = class_findmethod(c, name, desc);
2700 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2701 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2702 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2703 panic("Method not found");
2710 /************************* Function: class_findmethod_approx ******************
2712 like class_findmethod but ignores the return value when comparing the
2715 *******************************************************************************/
2717 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2721 for (i = 0; i < c->methodscount; i++) {
2722 if (c->methods[i].name == name) {
2723 utf *meth_descr = c->methods[i].descriptor;
2727 return &(c->methods[i]);
2729 if (desc->blength <= meth_descr->blength) {
2730 /* current position in utf text */
2731 char *desc_utf_ptr = desc->text;
2732 char *meth_utf_ptr = meth_descr->text;
2733 /* points behind utf strings */
2734 char *desc_end = utf_end(desc);
2735 char *meth_end = utf_end(meth_descr);
2738 /* compare argument types */
2739 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2741 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2742 break; /* no match */
2745 return &(c->methods[i]); /* all parameter types equal */
2755 /***************** Function: class_resolvemethod_approx ***********************
2757 Searches a class and every super class for a method (without paying
2758 attention to the return value)
2760 *******************************************************************************/
2762 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2765 /* search for method (ignore returntype) */
2766 methodinfo *m = class_findmethod_approx(c, name, desc);
2769 /* search superclass */
2777 /* class_resolvemethod *********************************************************
2779 Searches a class and it's super classes for a method.
2781 *******************************************************************************/
2783 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2788 m = class_findmethod(c, name, desc);
2800 /* class_resolveinterfacemethod_intern *****************************************
2802 Internally used helper function. Do not use this directly.
2804 *******************************************************************************/
2806 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
2807 utf *name, utf *desc)
2812 m = class_findmethod(c, name, desc);
2817 /* try the superinterfaces */
2819 for (i = 0; i < c->interfacescount; i++) {
2820 m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
2829 /* class_resolveinterfacemethod ************************************************
2831 Resolves a reference from REFERER to a method with NAME and DESC in
2834 If the method cannot be resolved the return value is NULL. If
2835 EXCEPT is true *exceptionptr is set, too.
2837 *******************************************************************************/
2839 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2840 classinfo *referer, bool except)
2844 /* XXX resolve class c */
2845 /* XXX check access from REFERER to C */
2847 if (!(c->flags & ACC_INTERFACE)) {
2850 new_exception(string_java_lang_IncompatibleClassChangeError);
2855 mi = class_resolveinterfacemethod_intern(c, name, desc);
2860 /* try class java.lang.Object */
2861 mi = class_findmethod(class_java_lang_Object, name, desc);
2868 new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
2874 /* class_resolveclassmethod ****************************************************
2876 Resolves a reference from REFERER to a method with NAME and DESC in
2879 If the method cannot be resolved the return value is NULL. If EXCEPT is
2880 true *exceptionptr is set, too.
2882 *******************************************************************************/
2884 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
2885 classinfo *referer, bool except)
2893 /* XXX resolve class c */
2894 /* XXX check access from REFERER to C */
2896 /* if (c->flags & ACC_INTERFACE) { */
2898 /* *exceptionptr = */
2899 /* new_exception(string_java_lang_IncompatibleClassChangeError); */
2903 /* try class c and its superclasses */
2908 mi = class_findmethod(cls, name, desc);
2916 /* try the superinterfaces */
2918 for (i = 0; i < c->interfacescount; i++) {
2919 mi = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
2926 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
2927 utf_strlen(desc) + strlen("0");
2929 msg = MNEW(char, msglen);
2931 utf_sprint(msg, c->name);
2933 utf_sprint(msg + strlen(msg), name);
2934 utf_sprint(msg + strlen(msg), desc);
2937 new_exception_message(string_java_lang_NoSuchMethodError, msg);
2939 MFREE(msg, char, msglen);
2945 if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
2947 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
2952 /* XXX check access rights */
2958 /************************* Function: class_issubclass **************************
2960 Checks if sub is a descendant of super.
2962 *******************************************************************************/
2964 bool class_issubclass(classinfo *sub, classinfo *super)
2967 if (!sub) return false;
2968 if (sub == super) return true;
2974 /****************** Initialization function for classes ******************
2976 In Java, every class can have a static initialization function. This
2977 function has to be called BEFORE calling other methods or accessing static
2980 *******************************************************************************/
2982 static classinfo *class_init_intern(classinfo *c);
2984 classinfo *class_init(classinfo *c)
2988 if (!makeinitializations)
2991 #if defined(USE_THREADS)
2992 /* enter a monitor on the class */
2994 builtin_monitorenter((java_objectheader *) c);
2997 /* maybe the class is already initalized or the current thread, which can
2998 pass the monitor, is currently initalizing this class */
3000 /* JOWENN: In future we need an additinal flag: initializationfailed,
3001 since further access to the class should cause a NoClassDefFound,
3002 if the static initializer failed once
3005 if (c->initialized || c->initializing) {
3006 #if defined(USE_THREADS)
3007 builtin_monitorexit((java_objectheader *) c);
3013 /* this initalizing run begins NOW */
3014 c->initializing = true;
3016 /* call the internal function */
3017 r = class_init_intern(c);
3019 /* if return value is not NULL everything was ok and the class is
3022 c->initialized = true;
3024 /* this initalizing run is done */
3025 c->initializing = false;
3027 #if defined(USE_THREADS)
3028 /* leave the monitor */
3030 builtin_monitorexit((java_objectheader *) c);
3037 /* this function MUST NOT be called directly, because of thread <clinit>
3040 static classinfo *class_init_intern(classinfo *c)
3044 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3048 /* maybe the class is not already loaded */
3050 if (!load_class_bootstrap(c))
3053 /* maybe the class is not already linked */
3058 #if defined(STATISTICS)
3060 count_class_inits++;
3063 /* initialize super class */
3066 if (!c->super->initialized) {
3068 char logtext[MAXLOGTEXT];
3069 sprintf(logtext, "Initialize super class ");
3070 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3071 sprintf(logtext + strlen(logtext), " from ");
3072 utf_sprint_classname(logtext + strlen(logtext), c->name);
3076 if (!class_init(c->super))
3081 /* initialize interface classes */
3083 for (i = 0; i < c->interfacescount; i++) {
3084 if (!c->interfaces[i]->initialized) {
3086 char logtext[MAXLOGTEXT];
3087 sprintf(logtext, "Initialize interface class ");
3088 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3089 sprintf(logtext + strlen(logtext), " from ");
3090 utf_sprint_classname(logtext + strlen(logtext), c->name);
3094 if (!class_init(c->interfaces[i]))
3099 m = class_findmethod(c, utf_clinit, utf_void__void);
3103 char logtext[MAXLOGTEXT];
3104 sprintf(logtext, "Class ");
3105 utf_sprint_classname(logtext + strlen(logtext), c->name);
3106 sprintf(logtext + strlen(logtext), " has no static class initializer");
3113 /* Sun's and IBM's JVM don't care about the static flag */
3114 /* if (!(m->flags & ACC_STATIC)) { */
3115 /* panic("Class initializer is not static!"); */
3118 log_message_class("Starting static class initializer for class: ", c);
3120 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3125 /* now call the initializer */
3126 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3128 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3129 assert(blockInts == 0);
3133 /* we have an exception or error */
3134 if (*exceptionptr) {
3135 /* class is NOT initialized */
3136 c->initialized = false;
3138 /* is this an exception, than wrap it */
3139 if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
3140 java_objectheader *xptr;
3141 java_objectheader *cause;
3144 cause = *exceptionptr;
3146 /* clear exception, because we are calling jit code again */
3147 *exceptionptr = NULL;
3149 /* wrap the exception */
3151 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3152 (java_lang_Throwable *) cause);
3154 /* XXX should we exit here? */
3158 /* set new exception */
3159 *exceptionptr = xptr;
3166 log_message_class("Finished static class initializer for class: ", c);
3172 void class_showconstanti(classinfo *c, int ii)
3178 printf ("#%d: ", (int) i);
3180 switch (c->cptags [i]) {
3181 case CONSTANT_Class:
3182 printf("Classreference -> ");
3183 utf_display(((classinfo*)e)->name);
3186 case CONSTANT_Fieldref:
3187 printf("Fieldref -> "); goto displayFMIi;
3188 case CONSTANT_Methodref:
3189 printf("Methodref -> "); goto displayFMIi;
3190 case CONSTANT_InterfaceMethodref:
3191 printf("InterfaceMethod -> "); goto displayFMIi;
3194 constant_FMIref *fmi = e;
3195 utf_display(fmi->class->name);
3197 utf_display(fmi->name);
3199 utf_display(fmi->descriptor);
3203 case CONSTANT_String:
3204 printf("String -> ");
3207 case CONSTANT_Integer:
3208 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3210 case CONSTANT_Float:
3211 printf("Float -> %f", ((constant_float*)e)->value);
3213 case CONSTANT_Double:
3214 printf("Double -> %f", ((constant_double*)e)->value);
3218 u8 v = ((constant_long*)e)->value;
3220 printf("Long -> %ld", (long int) v);
3222 printf("Long -> HI: %ld, LO: %ld\n",
3223 (long int) v.high, (long int) v.low);
3227 case CONSTANT_NameAndType:
3229 constant_nameandtype *cnt = e;
3230 printf("NameAndType: ");
3231 utf_display(cnt->name);
3233 utf_display(cnt->descriptor);
3241 panic("Invalid type of ConstantPool-Entry");
3248 void class_showconstantpool (classinfo *c)
3253 printf ("---- dump of constant pool ----\n");
3255 for (i=0; i<c->cpcount; i++) {
3256 printf ("#%d: ", (int) i);
3258 e = c -> cpinfos [i];
3261 switch (c -> cptags [i]) {
3262 case CONSTANT_Class:
3263 printf ("Classreference -> ");
3264 utf_display ( ((classinfo*)e) -> name );
3267 case CONSTANT_Fieldref:
3268 printf ("Fieldref -> "); goto displayFMI;
3269 case CONSTANT_Methodref:
3270 printf ("Methodref -> "); goto displayFMI;
3271 case CONSTANT_InterfaceMethodref:
3272 printf ("InterfaceMethod -> "); goto displayFMI;
3275 constant_FMIref *fmi = e;
3276 utf_display ( fmi->class->name );
3278 utf_display ( fmi->name);
3280 utf_display ( fmi->descriptor );
3284 case CONSTANT_String:
3285 printf ("String -> ");
3288 case CONSTANT_Integer:
3289 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3291 case CONSTANT_Float:
3292 printf ("Float -> %f", ((constant_float*)e) -> value);
3294 case CONSTANT_Double:
3295 printf ("Double -> %f", ((constant_double*)e) -> value);
3299 u8 v = ((constant_long*)e) -> value;
3301 printf ("Long -> %ld", (long int) v);
3303 printf ("Long -> HI: %ld, LO: %ld\n",
3304 (long int) v.high, (long int) v.low);
3308 case CONSTANT_NameAndType:
3310 constant_nameandtype *cnt = e;
3311 printf ("NameAndType: ");
3312 utf_display (cnt->name);
3314 utf_display (cnt->descriptor);
3318 printf ("Utf8 -> ");
3322 panic ("Invalid type of ConstantPool-Entry");
3332 /********** Function: class_showmethods (debugging only) *************/
3334 void class_showmethods (classinfo *c)
3338 printf ("--------- Fields and Methods ----------------\n");
3339 printf ("Flags: "); printflags (c->flags); printf ("\n");
3341 printf ("This: "); utf_display (c->name); printf ("\n");
3343 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3345 printf ("Index: %d\n", c->index);
3347 printf ("interfaces:\n");
3348 for (i=0; i < c-> interfacescount; i++) {
3350 utf_display (c -> interfaces[i] -> name);
3351 printf (" (%d)\n", c->interfaces[i] -> index);
3354 printf ("fields:\n");
3355 for (i=0; i < c -> fieldscount; i++) {
3356 field_display (&(c -> fields[i]));
3359 printf ("methods:\n");
3360 for (i=0; i < c -> methodscount; i++) {
3361 methodinfo *m = &(c->methods[i]);
3362 if ( !(m->flags & ACC_STATIC))
3363 printf ("vftblindex: %d ", m->vftblindex);
3365 method_display ( m );
3369 printf ("Virtual function table:\n");
3370 for (i=0; i<c->vftbl->vftbllength; i++) {
3371 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3377 /******************************************************************************/
3378 /******************* General functions for the class loader *******************/
3379 /******************************************************************************/
3381 /**************** function: class_primitive_from_sig ***************************
3383 return the primitive class indicated by the given signature character
3385 If the descriptor does not indicate a valid primitive type the
3386 return value is NULL.
3388 ********************************************************************************/
3390 classinfo *class_primitive_from_sig(char sig)
3393 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3394 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3395 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3396 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3397 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3398 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3399 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3400 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3401 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3406 /****************** function: class_from_descriptor ****************************
3408 return the class indicated by the given descriptor
3410 utf_ptr....first character of descriptor
3411 end_ptr....first character after the end of the string
3412 next.......if non-NULL, *next is set to the first character after
3413 the descriptor. (Undefined if an error occurs.)
3415 mode.......a combination (binary or) of the following flags:
3417 (Flags marked with * are the default settings.)
3419 What to do if a reference type descriptor is parsed successfully:
3421 CLASSLOAD_SKIP...skip it and return something != NULL
3422 * CLASSLOAD_NEW....get classinfo * via class_new
3423 CLASSLOAD_LOAD...get classinfo * via loader_load
3425 How to handle primitive types:
3427 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3428 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3430 How to handle "V" descriptors:
3432 * CLASSLOAD_VOID.....handle it like other primitive types
3433 CLASSLOAD_NOVOID...treat it as an error
3435 How to deal with extra characters after the end of the
3438 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3439 CLASSLOAD_CHECKEND.....treat them as an error
3441 How to deal with errors:
3443 * CLASSLOAD_PANIC....abort execution with an error message
3444 CLASSLOAD_NOPANIC..return NULL on error
3446 *******************************************************************************/
3448 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3449 char **next, int mode)
3451 char *start = utf_ptr;
3455 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3457 if (mode & CLASSLOAD_CHECKEND)
3458 error |= (utf_ptr != end_ptr);
3461 if (next) *next = utf_ptr;
3465 if (mode & CLASSLOAD_NOVOID)
3476 return (mode & CLASSLOAD_NULLPRIMITIVE)
3478 : class_primitive_from_sig(*start);
3485 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3486 name = utf_new(start, utf_ptr - start);
3490 tc = class_new_intern(name);
3491 load_class_from_classloader(tc, NULL);
3492 list_addfirst(&unlinkedclasses, tc);
3497 return (mode & CLASSLOAD_LOAD)
3498 ? load_class_from_classloader(class_new(name), NULL) : class_new(name); /* XXX handle errors */
3503 /* An error occurred */
3504 if (mode & CLASSLOAD_NOPANIC)
3507 log_plain("Invalid descriptor at beginning of '");
3508 log_plain_utf(utf_new(start, end_ptr - start));
3512 panic("Invalid descriptor");
3514 /* keep compiler happy */
3519 /******************* function: type_from_descriptor ****************************
3521 return the basic type indicated by the given descriptor
3523 This function parses a descriptor and returns its basic type as
3524 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3526 cls...if non-NULL the referenced variable is set to the classinfo *
3527 returned by class_from_descriptor.
3529 For documentation of the arguments utf_ptr, end_ptr, next and mode
3530 see class_from_descriptor. The only difference is that
3531 type_from_descriptor always uses CLASSLOAD_PANIC.
3533 ********************************************************************************/
3535 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3536 char **next, int mode)
3539 if (!cls) cls = &mycls;
3540 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3557 return TYPE_ADDRESS;
3561 /******************** Function: loader_close ***********************************
3565 *******************************************************************************/
3572 for (slot = 0; slot < class_hash.size; slot++) {
3573 c = class_hash.ptr[slot];
3584 * These are local overrides for various environment variables in Emacs.
3585 * Please do not remove this and leave it at the end of the file, where
3586 * Emacs will automagically detect them.
3587 * ---------------------------------------------------------------------
3590 * indent-tabs-mode: t