-/* loader.c - class loader functions
+/* vm/loader.c - class loader functions
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
- M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
- P. Tomsich, J. Wenninger
+ Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+ C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+ Institut f. Computersprachen - TU Wien
This file is part of CACAO.
Contact: cacao@complang.tuwien.ac.at
Authors: Reinhard Grafl
+
Changes: Andreas Krall
Roman Obermaiser
Mark Probst
- Edwin Steiner
+ Edwin Steiner
+ Christian Thalinger
- $Id: loader.c 1110 2004-05-28 21:45:51Z jowenn $
+ $Id: loader.c 1735 2004-12-07 14:33:27Z twisti $
*/
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
-#include "global.h"
-#include "loader.h"
-#include "main.h"
-#include "native.h"
-#include "tables.h"
-#include "builtin.h"
-#include "jit.h"
-#include "asmpart.h"
-#include "toolbox/memory.h"
+
+#include "mm/memory.h"
+#include "native/native.h"
+#include "native/include/java_lang_Throwable.h"
+
+#if defined(USE_THREADS)
+# if defined(NATIVE_THREADS)
+# include "threads/native/threads.h"
+# else
+# include "threads/green/threads.h"
+# include "threads/green/locks.h"
+# endif
+#endif
+
#include "toolbox/logging.h"
-#include "threads/thread.h"
-#include "threads/locks.h"
-#include "nat/java_lang_Throwable.h"
+#include "vm/exceptions.h"
+#include "vm/builtin.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/tables.h"
-#ifdef USE_ZLIB
-#include "unzip.h"
+#if defined(USE_ZLIB)
+# include "vm/unzip.h"
#endif
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+
+
#undef JOWENN_DEBUG
#undef JOWENN_DEBUG1
#undef JOWENN_DEBUG2
/* global variables ***********************************************************/
-int count_class_infos = 0; /* variables for measurements */
-int count_const_pool_len = 0;
-int count_vftbl_len = 0;
-int count_all_methods = 0;
-int count_vmcode_len = 0;
-int count_extable_len = 0;
-int count_class_loads = 0;
-int count_class_inits = 0;
-
static s4 interfaceindex; /* sequential numbering of interfaces */
static s4 classvalue;
static utf *utf_initializedesc;
static utf *utf_java_lang_Object; /* java/lang/Object */
+utf *utf_fillInStackTrace_name;
+utf *utf_fillInStackTrace_desc;
utf* clinit_desc(){
return utf_fidesc;
classinfo *pseudo_class_Arraystub = NULL;
classinfo *pseudo_class_Null = NULL;
classinfo *pseudo_class_New = NULL;
-vftbl *pseudo_class_Arraystub_vftbl = NULL;
+vftbl_t *pseudo_class_Arraystub_vftbl = NULL;
utf *array_packagename = NULL;
list of classpath entries (either filesystem directories or
ZIP/JAR archives
********************************************************************/
-static classpath_info *classpath_entries=0;
+
+static classpath_info *classpath_entries = NULL;
/******************************************************************************
};
-/* instances of important system classes **************************************/
-
-java_objectheader *proto_java_lang_NullPointerException;
-
-
/************* functions for reading classdata *********************************
getting classdata in blocks of variable size
*******************************************************************************/
-static char *classpath = ""; /* searchpath for classfiles */
+/* check_classbuffer_size ******************************************************
+
+ assert that at least <len> bytes are left to read
+ <len> is limited to the range of non-negative s4 values
+
+*******************************************************************************/
+
+static inline bool check_classbuffer_size(classbuffer *cb, s4 len)
+{
+ if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
+ *exceptionptr =
+ new_classformaterror((cb)->class, "Truncated class file");
+
+ return false;
+ }
+
+ return true;
+}
+
+/* suck_nbytes *****************************************************************
-/* assert that at least <len> bytes are left to read */
-/* <len> is limited to the range of non-negative s4 values */
+ transfer block of classfile data into a buffer
-#define ASSERT_LEFT(cb, len) \
- do { \
- if (((s4) (len)) < 0 || \
- (((cb)->data + (cb)->size) - (cb)->pos - 1) < (len)) { \
- char message[MAXLOGTEXT]; \
- utf_sprint_classname(message, (cb)->class->name); \
- sprintf(message + strlen(message), " (Truncated class file)"); \
- *exceptionptr = \
- new_exception_message(string_java_lang_ClassFormatError, \
- message); \
- throw_exception_exit(); \
- } \
- } while (0)
+*******************************************************************************/
+inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
+{
+ memcpy(buffer, cb->pos + 1, len);
+ cb->pos += len;
+}
-/* transfer block of classfile data into a buffer */
-#define suck_nbytes(buffer, cb, len) \
- do { \
- ASSERT_LEFT((cb), (len)); \
- memcpy((buffer), (cb)->pos + 1, (len)); \
- (cb)->pos += (len); \
- } while (0)
+/* skip_nbytes ****************************************************************
+ skip block of classfile data
-/* skip block of classfile data */
+*******************************************************************************/
-#define skip_nbytes(cb, len) \
- do { \
- ASSERT_LEFT((cb), (len)); \
- (cb)->pos += (len); \
- } while (0)
+inline void skip_nbytes(classbuffer *cb, s4 len)
+{
+ cb->pos += len;
+}
inline u1 suck_u1(classbuffer *cb)
{
- ASSERT_LEFT(cb, 1);
return *++(cb->pos);
}
return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
}
-#define suck_s8(a) (s8) suck_u8((a))
-#define suck_s2(a) (s2) suck_u2((a))
-#define suck_s4(a) (s4) suck_u4((a))
-#define suck_s1(a) (s1) suck_u1((a))
-
/* get u8 from classfile data */
static u8 suck_u8(classbuffer *cb)
}
+#define suck_s8(a) (s8) suck_u8((a))
+#define suck_s2(a) (s2) suck_u2((a))
+#define suck_s4(a) (s4) suck_u4((a))
+#define suck_s1(a) (s1) suck_u1((a))
+
+
/* get float from classfile data */
static float suck_float(classbuffer *cb)
{
buffer[3 - i] = suck_u1(cb);
memcpy((u1*) (&f), buffer, 4);
-#else
+#else
suck_nbytes((u1*) (&f), cb, 4);
#endif
if (sizeof(float) != 4) {
- *exceptionptr =
- new_exception_message(string_java_lang_InternalError,
- "Incompatible float-format");
+ *exceptionptr = new_exception_message(string_java_lang_InternalError,
+ "Incompatible float-format");
/* XXX should we exit in such a case? */
throw_exception_exit();
#endif
if (sizeof(double) != 8) {
- *exceptionptr =
- new_exception_message(string_java_lang_InternalError,
- "Incompatible double-format");
+ *exceptionptr = new_exception_message(string_java_lang_InternalError,
+ "Incompatible double-format");
/* XXX should we exit in such a case? */
throw_exception_exit();
*******************************************************************************/
-void suck_init(char *cpath)
+void suck_init(char *classpath)
{
- char *filename=0;
char *start;
char *end;
- int isZip;
- int filenamelen;
- union classpath_info *tmp;
- union classpath_info *insertAfter=0;
+ char *filename;
+ s4 filenamelen;
+ bool is_zip;
+ classpath_info *cpi;
+ classpath_info *lastcpi;
- if (!cpath)
+ if (!classpath)
return;
- classpath = cpath;
-
- if (classpath_entries)
- panic("suck_init should be called only once");
-
for (start = classpath; (*start) != '\0';) {
+
+ /* search for ':' delimiter to get the end of the current entry */
for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
if (start != end) {
- isZip = 0;
+ is_zip = false;
filenamelen = end - start;
- if (filenamelen>3) {
+ if (filenamelen > 3) {
if (strncasecmp(end - 3, "zip", 3) == 0 ||
strncasecmp(end - 3, "jar", 3) == 0) {
- isZip = 1;
+ is_zip = true;
}
}
- if (filenamelen >= (CLASSPATH_MAXFILENAME - 1))
- panic("path length >= MAXFILENAME in suck_init");
-
- if (!filename)
- filename = MNEW(char*, CLASSPATH_MAXFILENAME);
+ /* allocate memory for filename and fill it */
+ filename = MNEW(char, filenamelen + 2); /* 2 = "/\0" */
strncpy(filename, start, filenamelen);
filename[filenamelen + 1] = '\0';
- tmp = 0;
+ cpi = NULL;
- if (isZip) {
-#ifdef USE_ZLIB
+ if (is_zip) {
+#if defined(USE_ZLIB)
unzFile uf = unzOpen(filename);
if (uf) {
- tmp = (union classpath_info *) NEW(classpath_info);
- tmp->archive.type = CLASSPATH_ARCHIVE;
- tmp->archive.uf = uf;
- tmp->archive.next = 0;
- filename = 0;
+ cpi = (union classpath_info *) NEW(classpath_info);
+ cpi->archive.type = CLASSPATH_ARCHIVE;
+ cpi->archive.uf = uf;
+ cpi->archive.next = NULL;
}
#else
- panic("Zip/JAR not supported");
+ throw_cacao_exception_exit(string_java_lang_InternalError,
+ "zip/jar files not supported");
#endif
} else {
- tmp = (union classpath_info *) NEW(classpath_info);
- tmp->filepath.type = CLASSPATH_PATH;
- tmp->filepath.next = 0;
+ cpi = (union classpath_info *) NEW(classpath_info);
+ cpi->filepath.type = CLASSPATH_PATH;
+ cpi->filepath.next = NULL;
if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
filename[filenamelen] = '/';
filename[filenamelen + 1] = '\0';
filenamelen++;
}
-
- tmp->filepath.filename = filename;
- tmp->filepath.pathlen = filenamelen;
- filename = 0;
+
+ cpi->filepath.path = filename;
+ cpi->filepath.pathlen = filenamelen;
}
- if (tmp) {
- if (insertAfter) {
- insertAfter->filepath.next = tmp;
+ /* attach current classpath entry */
+
+ if (cpi) {
+ if (!classpath_entries) {
+ classpath_entries = cpi;
} else {
- classpath_entries = tmp;
+ lastcpi->filepath.next = cpi;
}
- insertAfter = tmp;
+
+ lastcpi = cpi;
}
}
- if ((*end) == ':')
+ /* goto next classpath entry, skip ':' delimiter */
+
+ if ((*end) == ':') {
start = end + 1;
- else
+
+ } else {
start = end;
-
- if (filename)
- MFREE(filename, char*, CLASSPATH_MAXFILENAME);
+ }
}
}
for (cpi = classpath_entries; cpi != 0; cpi = cpi->filepath.next) {
#if defined(USE_ZLIB)
- unz_file_info file_info;
if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
cacao_entry_s *ce;
unz_s *s;
classbuffer *suck_start(classinfo *c)
{
- classpath_info *currPos;
- char *utf_ptr;
- char ch;
- char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
- int filenamelen=0;
+ classpath_info *cpi;
+/* char *utf_ptr; */
+/* char ch; */
+ char *filename;
+ s4 filenamelen;
+ char *path;
FILE *classfile;
- int err;
+ bool found;
+ s4 len;
struct stat buffer;
classbuffer *cb;
+#if 0
utf_ptr = c->name->text;
while (utf_ptr < utf_end(c->name)) {
ch = '?';
filename[filenamelen++] = ch;
}
+#endif
+
+ /* initialize return value */
- strcpy(filename + filenamelen, ".class");
- filenamelen += 6;
+ found = false;
+ cb = NULL;
- for (currPos = classpath_entries; currPos != 0; currPos = currPos->filepath.next) {
-#ifdef USE_ZLIB
- if (currPos->filepath.type == CLASSPATH_ARCHIVE) {
- if (cacao_locate(currPos->archive.uf, c->name) == UNZ_OK) {
+ filenamelen = utf_strlen(c->name) + 7; /* 7 = ".class\0" */
+ filename = MNEW(char, filenamelen);
+
+ utf_sprint(filename, c->name);
+ strcat(filename, ".class");
+
+ /* walk through all classpath entries */
+
+ for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->filepath.next) {
+#if defined(USE_ZLIB)
+ if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
+ if (cacao_locate(cpi->archive.uf, c->name) == UNZ_OK) {
unz_file_info file_info;
- /*log_text("Class found in zip file");*/
- if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
- sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
- if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
+
+ if (unzGetCurrentFileInfo(cpi->archive.uf, &file_info, filename,
+ sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
+ if (unzOpenCurrentFile(cpi->archive.uf) == UNZ_OK) {
cb = NEW(classbuffer);
cb->class = c;
cb->size = file_info.uncompressed_size;
cb->data = MNEW(u1, cb->size);
cb->pos = cb->data - 1;
- /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
- if (unzReadCurrentFile(currPos->archive.uf, cb->data, cb->size) == cb->size) {
- unzCloseCurrentFile(currPos->archive.uf);
- return cb;
- } else {
- MFREE(cb->data, u1, cb->size);
- FREE(cb, classbuffer);
+ len = unzReadCurrentFile(cpi->archive.uf, cb->data, cb->size);
+
+ if (len != cb->size) {
+ suck_stop(cb);
log_text("Error while unzipping");
+
+ } else {
+ found = true;
}
- } else log_text("Error while opening file in archive");
- } else log_text("Error while retrieving fileinfo");
+
+ } else {
+ log_text("Error while opening file in archive");
+ }
+
+ } else {
+ log_text("Error while retrieving fileinfo");
+ }
}
- unzCloseCurrentFile(currPos->archive.uf);
+ unzCloseCurrentFile(cpi->archive.uf);
} else {
-#endif
- if ((currPos->filepath.pathlen + filenamelen) >= CLASSPATH_MAXFILENAME) continue;
- strcpy(currPos->filepath.filename + currPos->filepath.pathlen, filename);
- classfile = fopen(currPos->filepath.filename, "r");
- if (classfile) { /* file exists */
-
- /* determine size of classfile */
+#endif /* USE_ZLIB */
+
+ path = MNEW(char, cpi->filepath.pathlen + filenamelen + 1);
+ strcpy(path, cpi->filepath.path);
+ strcat(path, filename);
- /* dolog("File: %s",filename); */
- err = stat(currPos->filepath.filename, &buffer);
+ classfile = fopen(path, "r");
- if (!err) { /* read classfile data */
+ if (classfile) { /* file exists */
+ if (!stat(path, &buffer)) { /* read classfile data */
cb = NEW(classbuffer);
cb->class = c;
cb->size = buffer.st_size;
cb->data = MNEW(u1, cb->size);
cb->pos = cb->data - 1;
- fread(cb->data, 1, cb->size, classfile);
- fclose(classfile);
- return cb;
+ /* read class data */
+ len = fread(cb->data, 1, cb->size, classfile);
+
+ if (len != buffer.st_size) {
+ suck_stop(cb);
+/* if (ferror(classfile)) { */
+/* } */
+
+ } else {
+ found = true;
+ }
}
}
-#ifdef USE_ZLIB
+
+ MFREE(path, char, cpi->filepath.pathlen + filenamelen + 1);
+#if defined(USE_ZLIB)
}
#endif
}
- if (verbose) {
- dolog("Warning: Can not open class file '%s'", filename);
+ if (opt_verbose) {
+ if (!found)
+ dolog("Warning: Can not open class file '%s'", filename);
}
- return NULL;
+ MFREE(filename, char, filenamelen);
+
+ return cb;
}
}
-/************************* Function: skipattribute *****************************
-
- skips a (1) 'attribute' structure in the class file
+/********************** Function: skipattributebody ****************************
+ skips an attribute after the 16 bit reference to attribute_name has already
+ been read
+
*******************************************************************************/
-static void skipattribute(classbuffer *cb)
+static bool skipattributebody(classbuffer *cb)
{
u4 len;
- suck_u2(cb);
+
+ if (!check_classbuffer_size(cb, 4))
+ return false;
+
len = suck_u4(cb);
+
+ if (!check_classbuffer_size(cb, len))
+ return false;
+
skip_nbytes(cb, len);
+
+ return true;
}
-/********************** Function: skipattributebody ****************************
+/************************* Function: skipattributes ****************************
- skips an attribute after the 16 bit reference to attribute_name has already
- been read
+ skips num attribute structures
*******************************************************************************/
-static void skipattributebody(classbuffer *cb)
+static bool skipattributes(classbuffer *cb, u4 num)
{
+ u4 i;
u4 len;
- len = suck_u4(cb);
- skip_nbytes(cb, len);
+
+ for (i = 0; i < num; i++) {
+ if (!check_classbuffer_size(cb, 2 + 4))
+ return false;
+
+ suck_u2(cb);
+ len = suck_u4(cb);
+
+ if (!check_classbuffer_size(cb, len))
+ return false;
+
+ skip_nbytes(cb, len);
+ }
+
+ return true;
}
-/************************* Function: skipattributes ****************************
+/******************** function:: class_getconstant *****************************
+
+ retrieves the value at position 'pos' of the constantpool of a class
+ if the type of the value is other than 'ctype' the system is stopped
- skips num attribute structures
-
*******************************************************************************/
-static void skipattributes(classbuffer *cb, u4 num)
+voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
{
- u4 i;
- for (i = 0; i < num; i++)
- skipattribute(cb);
+ /* check index and type of constantpool entry */
+ /* (pos == 0 is caught by type comparison) */
+ if (pos >= c->cpcount || c->cptags[pos] != ctype) {
+ *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ return c->cpinfos[pos];
}
*******************************************************************************/
-voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
+voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
{
/* invalid position in constantpool */
- if (pos >= c->cpcount)
- panic("Attempt to access constant outside range");
+ if (pos >= c->cpcount) {
+ *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
/* constantpool entry of type 0 */
if (!c->cptags[pos])
/* check type of constantpool entry */
if (c->cptags[pos] != ctype) {
- error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
- (int) ctype, (int) c->cptags[pos] );
+ *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+ return NULL;
}
return c->cpinfos[pos];
}
+/********************* Function: class_constanttype ****************************
+
+ Determines the type of a class entry in the ConstantPool
+
+*******************************************************************************/
+
+u4 class_constanttype(classinfo *c, u4 pos)
+{
+ if (pos <= 0 || pos >= c->cpcount) {
+ *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+ return 0;
+ }
+
+ return c->cptags[pos];
+}
+
+
/************************ function: attribute_load ****************************
read attributes from classfile
*******************************************************************************/
-static void attribute_load(classbuffer *cb, classinfo *c, u4 num)
+static bool attribute_load(classbuffer *cb, classinfo *c, u4 num)
{
+ utf *aname;
u4 i, j;
for (i = 0; i < num; i++) {
/* retrieve attribute name */
- utf *aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
+ if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
if (aname == utf_innerclasses) {
/* innerclasses attribute */
-
- if (c->innerclass != NULL)
- panic("Class has more than one InnerClasses attribute");
+ if (c->innerclass) {
+ *exceptionptr =
+ new_classformaterror(c, "Multiple InnerClasses attributes");
+ return false;
+ }
- /* skip attribute length */
- suck_u4(cb);
+ if (!check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* skip attribute length */
+ suck_u4(cb);
+
/* number of records */
c->innerclasscount = suck_u2(cb);
+
+ if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
+ return false;
+
/* allocate memory for innerclass structure */
c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
for (j = 0; j < c->innerclasscount; j++) {
- /* The innerclass structure contains a class with an encoded name,
- its defining scope, its simple name and a bitmask of the access flags.
- If an inner class is not a member, its outer_class is NULL,
- if a class is anonymous, its name is NULL. */
+ /* The innerclass structure contains a class with an encoded
+ name, its defining scope, its simple name and a bitmask of
+ the access flags. If an inner class is not a member, its
+ outer_class is NULL, if a class is anonymous, its name is
+ NULL. */
innerclassinfo *info = c->innerclass + j;
- info->inner_class = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); /* CONSTANT_Class_info index */
- info->outer_class = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); /* CONSTANT_Class_info index */
- info->name = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
- info->flags = suck_u2(cb); /* access_flags bitmask */
+ info->inner_class =
+ innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ info->outer_class =
+ innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ info->name =
+ innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+ info->flags = suck_u2(cb);
}
- } else if (aname==utf_sourcefile) {
- suck_u4(cb);
- /*log_text("source file attribute found");*/
- c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+
+ } else if (aname == utf_sourcefile) {
+ if (!check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ if (suck_u4(cb) != 2) {
+ *exceptionptr =
+ new_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ if (c->sourcefile) {
+ *exceptionptr =
+ new_classformaterror(c, "Multiple SourceFile attributes");
+ return false;
+ }
+
+ if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
} else {
/* unknown attribute */
- skipattributebody(cb);
+ if (!skipattributebody(cb))
+ return false;
}
}
+
+ return true;
}
*******************************************************************************/
-static int checkmethoddescriptor (utf *d)
+static int checkmethoddescriptor(classinfo *c, utf *descriptor)
{
- char *utf_ptr = d->text; /* current position in utf text */
- char *end_pos = utf_end(d); /* points behind utf string */
- int argcount = 0; /* number of arguments */
+ char *utf_ptr; /* current position in utf text */
+ char *end_pos; /* points behind utf string */
+ s4 argcount = 0; /* number of arguments */
+
+ utf_ptr = descriptor->text;
+ end_pos = utf_end(descriptor);
/* method descriptor must start with parenthesis */
- if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
+ if (utf_ptr == end_pos || *utf_ptr++ != '(')
+ panic ("Missing '(' in method descriptor");
/* check arguments */
while (utf_ptr != end_pos && *utf_ptr != ')') {
| CLASSLOAD_NOVOID);
}
- if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
+ if (utf_ptr == end_pos)
+ panic("Missing ')' in method descriptor");
+
utf_ptr++; /* skip ')' */
- class_from_descriptor(utf_ptr,end_pos,NULL,
- CLASSLOAD_NEW
- | CLASSLOAD_NULLPRIMITIVE
- | CLASSLOAD_CHECKEND);
+ class_from_descriptor(utf_ptr,
+ end_pos,
+ NULL,
+ CLASSLOAD_NEW |
+ CLASSLOAD_NULLPRIMITIVE |
+ CLASSLOAD_CHECKEND);
+
+ if (argcount > 255) {
+ *exceptionptr =
+ new_classformaterror(c, "Too many arguments in signature");
- if (argcount > 255)
- panic("Invalid method descriptor: too many arguments");
+ return 0;
+ }
return argcount;
/******************************************************************************/
-/************************ Function: field_load *********************************
+/* field_load ******************************************************************
- Load everything about a class field from the class file and fill a
- 'fieldinfo' structure. For static fields, space in the data segment is
- allocated.
+ Load everything about a class field from the class file and fill a
+ 'fieldinfo' structure. For static fields, space in the data segment is
+ allocated.
*******************************************************************************/
#define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
-static fieldinfo *field_load(classbuffer *cb, classinfo *c, fieldinfo *f)
+static bool field_load(classbuffer *cb, classinfo *c, fieldinfo *f)
{
- u4 attrnum,i;
+ u4 attrnum, i;
u4 jtype;
- u4 pindex = field_load_NOVALUE; /* constantvalue_index */
+ u4 pindex = field_load_NOVALUE; /* constantvalue_index */
+ utf *u;
+
+ if (!check_classbuffer_size(cb, 2 + 2 + 2))
+ return false;
+
+ f->flags = suck_u2(cb);
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+ f->name = u;
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+ f->descriptor = u;
- f->flags = suck_u2(cb); /* ACC flags */
- f->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* name of field */
- f->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8); /* JavaVM descriptor */
-
if (opt_verify) {
/* check name */
if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
panic("Field with invalid name");
/* check flag consistency */
- i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
- if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
- panic("Field has invalid access flags");
- if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
- panic("Field is declared final and volatile");
- if ((c->flags & ACC_INTERFACE) != 0) {
- if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
- != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
- panic("Interface field is not declared static final public");
- if ((f->flags & ACC_TRANSIENT) != 0)
- panic("Interface field declared transient");
+ i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
+
+ if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
+ ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
+ *exceptionptr =
+ new_classformaterror(c,
+ "Illegal field modifiers: 0x%X",
+ f->flags);
+ return false;
+ }
+
+ if (c->flags & ACC_INTERFACE) {
+ if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
+ != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
+ f->flags & ACC_TRANSIENT) {
+ *exceptionptr =
+ new_classformaterror(c,
+ "Illegal field modifiers: 0x%X",
+ f->flags);
+ return false;
+ }
}
/* check descriptor */
- checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
+ checkfielddescriptor(f->descriptor->text, utf_end(f->descriptor));
}
- f->type = jtype = desc_to_type(f->descriptor); /* data type */
- f->offset = 0; /* offset from start of object */
+ f->type = jtype = desc_to_type(f->descriptor); /* data type */
+ f->offset = 0; /* offset from start of object */
f->class = c;
f->xta = NULL;
switch (f->type) {
- case TYPE_INT: f->value.i = 0; break;
- case TYPE_FLOAT: f->value.f = 0.0; break;
- case TYPE_DOUBLE: f->value.d = 0.0; break;
- case TYPE_ADDRESS: f->value.a = NULL; break;
+ case TYPE_INT: f->value.i = 0; break;
+ case TYPE_FLOAT: f->value.f = 0.0; break;
+ case TYPE_DOUBLE: f->value.d = 0.0; break;
+ case TYPE_ADDRESS: f->value.a = NULL; break;
case TYPE_LONG:
#if U8_AVAILABLE
f->value.l = 0; break;
}
/* read attributes */
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
attrnum = suck_u2(cb);
for (i = 0; i < attrnum; i++) {
- utf *aname;
+ if (!check_classbuffer_size(cb, 2))
+ return false;
- aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
-
- if (aname != utf_constantvalue) {
- /* unknown attribute */
- skipattributebody(cb);
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
- } else {
- /* constant value attribute */
+ if (u == utf_constantvalue) {
+ if (!check_classbuffer_size(cb, 4 + 2))
+ return false;
- if (pindex != field_load_NOVALUE)
- panic("Field has more than one ConstantValue attribute");
-
/* check attribute length */
- if (suck_u4(cb) != 2)
- panic("ConstantValue attribute has invalid length");
+ if (suck_u4(cb) != 2) {
+ *exceptionptr =
+ new_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* constant value attribute */
+ if (pindex != field_load_NOVALUE) {
+ *exceptionptr =
+ new_classformaterror(c,
+ "Multiple ConstantValue attributes");
+ return false;
+ }
/* index of value in constantpool */
pindex = suck_u2(cb);
/* initialize field with value from constantpool */
switch (jtype) {
case TYPE_INT: {
- constant_integer *ci =
- class_getconstant(c, pindex, CONSTANT_Integer);
+ constant_integer *ci;
+
+ if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
+ return false;
+
f->value.i = ci->value;
}
break;
case TYPE_LONG: {
- constant_long *cl =
- class_getconstant(c, pindex, CONSTANT_Long);
+ constant_long *cl;
+
+ if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
+ return false;
+
f->value.l = cl->value;
}
break;
case TYPE_FLOAT: {
- constant_float *cf =
- class_getconstant(c, pindex, CONSTANT_Float);
+ constant_float *cf;
+
+ if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
+ return false;
+
f->value.f = cf->value;
}
break;
case TYPE_DOUBLE: {
- constant_double *cd =
- class_getconstant(c, pindex, CONSTANT_Double);
+ constant_double *cd;
+
+ if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
+ return false;
+
f->value.d = cd->value;
}
break;
- case TYPE_ADDRESS: {
- utf *u = class_getconstant(c, pindex, CONSTANT_String);
- /* create javastring from compressed utf8-string */
+ case TYPE_ADDRESS:
+ if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
+ return false;
+
+ /* create javastring from compressed utf8-string */
f->value.a = literalstring_new(u);
- }
- break;
+ break;
default:
- log_text ("Invalid Constant - Type");
+ log_text("Invalid Constant - Type");
}
+
+ } else {
+ /* unknown attribute */
+ if (!skipattributebody(cb))
+ return false;
}
}
- /* just return fieldinfo* to signal everything was ok */
+ /* everything was ok */
- return f;
+ return true;
}
/******************************************************************************/
-/*********************** Function: method_load *********************************
+/* method_load *****************************************************************
- Loads a method from the class file and fills an existing 'methodinfo'
- structure. For native methods, the function pointer field is set to the
- real function pointer, for JavaVM methods a pointer to the compiler is used
- preliminarily.
+ Loads a method from the class file and fills an existing 'methodinfo'
+ structure. For native methods, the function pointer field is set to the
+ real function pointer, for JavaVM methods a pointer to the compiler is used
+ preliminarily.
*******************************************************************************/
-static methodinfo *method_load(classbuffer *cb, classinfo *c, methodinfo *m)
+static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m)
{
- u4 attrnum, i, e;
s4 argcount;
- char msg[MAXLOGTEXT]; /* maybe we get an exception */
+ s4 i, j;
+ u4 attrnum;
+ u4 codeattrnum;
+ utf *u;
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ initObjectLock(&m->header);
+#endif
#ifdef STATISTICS
if (opt_stat)
m->linenumbercount = 0;
m->linenumbers = 0;
m->class = c;
+ m->nativelyoverloaded = false;
+ if (!check_classbuffer_size(cb, 2 + 2 + 2))
+ return false;
+
m->flags = suck_u2(cb);
- m->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+ m->name = u;
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+ m->descriptor = u;
if (opt_verify) {
if (!is_valid_name_utf(m->name))
panic("Method with invalid name");
+
if (m->name->text[0] == '<'
&& m->name != utf_init && m->name != utf_clinit)
panic("Method with invalid special name");
}
- m->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
- argcount = checkmethoddescriptor(m->descriptor);
+ argcount = checkmethoddescriptor(c, m->descriptor);
+
if (!(m->flags & ACC_STATIC))
argcount++; /* count the 'this' argument */
if (opt_verify) {
- if (argcount > 255)
- panic("Too many arguments in signature");
+ if (argcount > 255) {
+ *exceptionptr =
+ new_classformaterror(c, "Too many arguments in signature");
+ return false;
+ }
/* check flag consistency */
if (m->name != utf_clinit) {
i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
- if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
- panic("Method has invalid access flags");
- if ((m->flags & ACC_ABSTRACT) != 0) {
+ if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
+ *exceptionptr =
+ new_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
+ }
+
+ if (m->flags & ACC_ABSTRACT) {
if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg), " (Illegal method modifiers: 0x%x)", m->flags);
-
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError,
- msg);
-
- return NULL;
+ new_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
}
}
- if ((c->flags & ACC_INTERFACE) != 0) {
- if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
- != (ACC_ABSTRACT | ACC_PUBLIC))
- panic("Interface method is not declared abstract and public");
+ if (c->flags & ACC_INTERFACE) {
+ if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
+ *exceptionptr =
+ new_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
+ }
}
if (m->name == utf_init) {
- if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
- | ACC_NATIVE | ACC_ABSTRACT)) != 0)
+ if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
+ ACC_NATIVE | ACC_ABSTRACT))
panic("Instance initialization method has invalid flags set");
}
}
}
m->jcode = NULL;
+ m->basicblockcount = 0;
+ m->basicblocks = NULL;
+ m->basicblockindex = NULL;
+ m->instructioncount = 0;
+ m->instructions = NULL;
+ m->stackcount = 0;
+ m->stack = NULL;
m->exceptiontable = NULL;
- m->entrypoint = NULL;
- m->mcode = NULL;
m->stubroutine = NULL;
+ m->mcode = NULL;
+ m->entrypoint = NULL;
m->methodUsed = NOTUSED;
m->monoPoly = MONO;
m->subRedefs = 0;
m->stubroutine = createcompilerstub(m);
} else {
+ /*if (useinlining) {
+ log_text("creating native stub:");
+ method_display(m);
+ }*/
functionptr f = native_findfunction(c->name, m->name, m->descriptor,
- (m->flags & ACC_STATIC) != 0);
- if (f) {
+ (m->flags & ACC_STATIC) != 0);
+#ifdef STATIC_CLASSPATH
+ if (f)
+#endif
+ {
m->stubroutine = createnativestub(f, m);
}
}
+ if (!check_classbuffer_size(cb, 2))
+ return false;
attrnum = suck_u2(cb);
for (i = 0; i < attrnum; i++) {
utf *aname;
- aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
-
- if (aname != utf_code) {
- if (aname == utf_exceptions) {
- u2 exceptionCount;
- u2 exceptionID;
- suck_u4(cb); /*length*/
- exceptionCount=suck_u2(cb);
- m->thrownexceptionscount=exceptionCount;
- m->thrownexceptions=MNEW(classinfo*,exceptionCount);
- for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
- (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(cb),CONSTANT_Class);
- }
- }
- else
- skipattributebody(cb);
+ if (!check_classbuffer_size(cb, 2))
+ return false;
- } else {
- u4 codelen;
- if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg),
- " (Code attribute in native or abstract methods)");
+ if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+ if (aname == utf_code) {
+ if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError,
- msg);
+ new_classformaterror(c,
+ "Code attribute in native or abstract methods");
- return NULL;
+ return false;
}
if (m->jcode) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg), " (Multiple Code attributes)");
-
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError,
- msg);
+ new_classformaterror(c, "Multiple Code attributes");
- return NULL;
+ return false;
}
+ if (!check_classbuffer_size(cb, 4 + 2 + 2))
+ return false;
+
suck_u4(cb);
m->maxstack = suck_u2(cb);
m->maxlocals = suck_u2(cb);
- if (m->maxlocals < argcount) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg),
- " (Arguments can't fit into locals)");
+ if (m->maxlocals < argcount) {
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError,
- msg);
+ new_classformaterror(c, "Arguments can't fit into locals");
- return NULL;
+ return false;
}
- codelen = suck_u4(cb);
+ if (!check_classbuffer_size(cb, 4))
+ return false;
- if (codelen == 0)
- panic("bytecode has zero length");
+ m->jcodelength = suck_u4(cb);
- if (codelen > 65535) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg),
- " (Code of a method longer than 65535 bytes)");
+ if (m->jcodelength == 0) {
+ *exceptionptr =
+ new_classformaterror(c, "Code of a method has length 0");
+ return false;
+ }
+
+ if (m->jcodelength > 65535) {
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError,
- msg);
+ new_classformaterror(c,
+ "Code of a method longer than 65535 bytes");
- return NULL;
+ return false;
}
- m->jcodelength = codelen;
+ if (!check_classbuffer_size(cb, m->jcodelength))
+ return false;
+
m->jcode = MNEW(u1, m->jcodelength);
suck_nbytes(m->jcode, cb, m->jcodelength);
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
m->exceptiontablelength = suck_u2(cb);
- m->exceptiontable =
- MNEW(exceptiontable, m->exceptiontablelength);
+ if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
+ return false;
-#ifdef STATISTICS
+ m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
+
+#if defined(STATISTICS)
if (opt_stat) {
count_vmcode_len += m->jcodelength + 18;
count_extable_len += 8 * m->exceptiontablelength;
}
#endif
- for (e = 0; e < m->exceptiontablelength; e++) {
+ for (j = 0; j < m->exceptiontablelength; j++) {
u4 idx;
- m->exceptiontable[e].startpc = suck_u2(cb);
- m->exceptiontable[e].endpc = suck_u2(cb);
- m->exceptiontable[e].handlerpc = suck_u2(cb);
+ m->exceptiontable[j].startpc = suck_u2(cb);
+ m->exceptiontable[j].endpc = suck_u2(cb);
+ m->exceptiontable[j].handlerpc = suck_u2(cb);
idx = suck_u2(cb);
if (!idx) {
- m->exceptiontable[e].catchtype = NULL;
+ m->exceptiontable[j].catchtype = NULL;
} else {
- m->exceptiontable[e].catchtype =
- class_getconstant(c, idx, CONSTANT_Class);
+ if (!(m->exceptiontable[j].catchtype =
+ class_getconstant(c, idx, CONSTANT_Class)))
+ return false;
}
- }
- {
- u2 codeattrnum;
- for (codeattrnum=suck_u2(cb);codeattrnum>0;codeattrnum--) {
- utf * caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
- if (caname==utf_linenumbertable) {
- u2 lncid;
- /*log_text("LineNumberTable found");*/
- suck_u4(cb);
- m->linenumbercount=suck_u2(cb);
- /*printf("length:%d\n",m->linenumbercount);*/
- m->linenumbers=MNEW(lineinfo,m->linenumbercount);
- for (lncid=0;lncid<m->linenumbercount;lncid++) {
- m->linenumbers[lncid].start_pc=suck_u2(cb);
- m->linenumbers[lncid].line_number=suck_u2(cb);
- }
- codeattrnum--;
- skipattributes(cb, codeattrnum);
- break;
- } else skipattributebody(cb);
+ }
+
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
+ codeattrnum = suck_u2(cb);
+
+ for (; codeattrnum > 0; codeattrnum--) {
+ utf *caname;
+
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
+ if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
+ if (caname == utf_linenumbertable) {
+ u2 lncid;
+
+ if (!check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ suck_u4(cb);
+ m->linenumbercount = suck_u2(cb);
+
+ if (!check_classbuffer_size(cb,
+ (2 + 2) * m->linenumbercount))
+ return false;
+
+ m->linenumbers = MNEW(lineinfo, m->linenumbercount);
+
+ for (lncid = 0; lncid < m->linenumbercount; lncid++) {
+ m->linenumbers[lncid].start_pc = suck_u2(cb);
+ m->linenumbers[lncid].line_number = suck_u2(cb);
+ }
+ codeattrnum--;
+
+ if (!skipattributes(cb, codeattrnum))
+ return false;
- }
+ break;
+
+ } else {
+ if (!skipattributebody(cb))
+ return false;
+ }
+ }
+
+ } else if (aname == utf_exceptions) {
+ s4 j;
+
+ if (m->thrownexceptions) {
+ *exceptionptr =
+ new_classformaterror(c, "Multiple Exceptions attributes");
+ return false;
}
+
+ if (!check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ suck_u4(cb); /* length */
+ m->thrownexceptionscount = suck_u2(cb);
+
+ if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
+ return false;
+
+ m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
+
+ for (j = 0; j < m->thrownexceptionscount; j++) {
+ if (!((m->thrownexceptions)[j] =
+ class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+ return false;
+ }
+
+ } else {
+ if (!skipattributebody(cb))
+ return false;
}
}
if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg), " (Missing Code attribute)");
-
- *exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError, msg);
+ *exceptionptr = new_classformaterror(c, "Missing Code attribute");
- return NULL;
+ return false;
}
- /* just return methodinfo* to signal everything was ok */
+ /* everything was ok */
+ /* utf_display(m->name);
+ printf("\nexceptiontablelength:%ld\n",m->exceptiontablelength);*/
- return m;
+ return true;
}
printf("\n");
}
+/************** Function: method_display_w_class (debugging only) **************/
+
+void method_display_w_class(methodinfo *m)
+{
+ printflags(m->class->flags);
+ printf(" "); fflush(stdout);
+ utf_display(m->class->name);
+ printf(".");fflush(stdout);
+
+ printf(" ");
+ printflags(m->flags);
+ printf(" "); fflush(stdout);
+ utf_display(m->name);
+ printf(" "); fflush(stdout);
+ utf_display(m->descriptor);
+ printf("\n"); fflush(stdout);
+}
+
/************** Function: method_display_flags_last (debugging only) **************/
void method_display_flags_last(methodinfo *m)
}
-/******************************************************************************/
-/************************ Functions for class *********************************/
-/******************************************************************************/
-
-
-/******************** function:: class_getconstant *****************************
-
- retrieves the value at position 'pos' of the constantpool of a class
- if the type of the value is other than 'ctype' the system is stopped
-
-*******************************************************************************/
-
-voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
-{
- /* invalid position in constantpool */
- /* (pos == 0 is caught by type comparison) */
- if (pos >= c->cpcount)
- panic("Attempt to access constant outside range");
-
- /* check type of constantpool entry */
-
- if (c->cptags[pos] != ctype) {
- class_showconstantpool(c);
- error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
- (int) ctype, (int) c->cptags[pos]);
- }
-
- return c->cpinfos[pos];
-}
-
-
-/********************* Function: class_constanttype ****************************
-
- Determines the type of a class entry in the ConstantPool
-
-*******************************************************************************/
-
-u4 class_constanttype(classinfo *c, u4 pos)
-{
- if (pos >= c->cpcount)
- panic("Attempt to access constant outside range");
-
- return c->cptags[pos];
-}
-
-
/******************** function: class_loadcpool ********************************
loads the constantpool of a class,
*******************************************************************************/
-static void class_loadcpool(classbuffer *cb, classinfo *c)
+static bool class_loadcpool(classbuffer *cb, classinfo *c)
{
/* The following structures are used to save information which cannot be
been traversed the references can be resolved.
(only in specific order) */
- /* CONSTANT_Class_info entries */
- typedef struct forward_class {
- struct forward_class *next;
- u2 thisindex;
- u2 name_index;
- } forward_class;
-
- /* CONSTANT_String */
- typedef struct forward_string {
- struct forward_string *next;
- u2 thisindex;
+ /* CONSTANT_Class entries */
+ typedef struct forward_class {
+ struct forward_class *next;
+ u2 thisindex;
+ u2 name_index;
+ } forward_class;
+
+ /* CONSTANT_String */
+ typedef struct forward_string {
+ struct forward_string *next;
+ u2 thisindex;
u2 string_index;
} forward_string;
} forward_nameandtype;
/* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
- typedef struct forward_fieldmethint {
+ typedef struct forward_fieldmethint {
struct forward_fieldmethint *next;
u2 thisindex;
u1 tag;
u4 idx;
- long int dumpsize = dump_size ();
forward_class *forward_classes = NULL;
forward_string *forward_strings = NULL;
forward_nameandtype *forward_nameandtypes = NULL;
forward_fieldmethint *forward_fieldmethints = NULL;
+ forward_class *nfc;
+ forward_string *nfs;
+ forward_nameandtype *nfn;
+ forward_fieldmethint *nff;
+
+ u4 cpcount;
+ u1 *cptags;
+ voidptr *cpinfos;
+
/* number of entries in the constant_pool table plus one */
- u4 cpcount = c->cpcount = suck_u2(cb);
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
+ cpcount = c->cpcount = suck_u2(cb);
/* allocate memory */
- u1 *cptags = c->cptags = MNEW(u1, cpcount);
- voidptr *cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
+ cptags = c->cptags = MNEW(u1, cpcount);
+ cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
- if (!cpcount)
- panic("Invalid constant_pool_count (0)");
+ if (cpcount < 1) {
+ *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
+ return false;
+ }
-#ifdef STATISTICS
- count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
#endif
/* initialize constantpool */
idx = 1;
while (idx < cpcount) {
+ u4 t;
+
/* get constant type */
- u4 t = suck_u1(cb);
+ if (!check_classbuffer_size(cb, 1))
+ return false;
+
+ t = suck_u1(cb);
switch (t) {
- case CONSTANT_Class: {
- forward_class *nfc = DNEW(forward_class);
+ case CONSTANT_Class:
+ nfc = NEW(forward_class);
- nfc->next = forward_classes;
+ nfc->next = forward_classes;
forward_classes = nfc;
nfc->thisindex = idx;
/* reference to CONSTANT_NameAndType */
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
nfc->name_index = suck_u2(cb);
idx++;
break;
- }
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref: {
- forward_fieldmethint *nff = DNEW(forward_fieldmethint);
-
- nff->next = forward_fieldmethints;
- forward_fieldmethints = nff;
-
- nff->thisindex = idx;
- /* constant type */
- nff->tag = t;
- /* class or interface type that contains the declaration of the
- field or method */
- nff->class_index = suck_u2(cb);
- /* name and descriptor of the field or method */
- nff->nameandtype_index = suck_u2(cb);
-
- idx++;
- break;
- }
-
- case CONSTANT_String: {
- forward_string *nfs = DNEW(forward_string);
+ case CONSTANT_String:
+ nfs = NEW(forward_string);
nfs->next = forward_strings;
forward_strings = nfs;
nfs->thisindex = idx;
+
/* reference to CONSTANT_Utf8_info with string characters */
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
nfs->string_index = suck_u2(cb);
idx++;
break;
- }
- case CONSTANT_NameAndType: {
- forward_nameandtype *nfn = DNEW(forward_nameandtype);
+ case CONSTANT_NameAndType:
+ nfn = NEW(forward_nameandtype);
nfn->next = forward_nameandtypes;
forward_nameandtypes = nfn;
nfn->thisindex = idx;
+
+ if (!check_classbuffer_size(cb, 2 + 2))
+ return false;
+
/* reference to CONSTANT_Utf8_info containing simple name */
nfn->name_index = suck_u2(cb);
+
/* reference to CONSTANT_Utf8_info containing field or method
descriptor */
nfn->sig_index = suck_u2(cb);
idx++;
break;
- }
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ nff = NEW(forward_fieldmethint);
+
+ nff->next = forward_fieldmethints;
+ forward_fieldmethints = nff;
+
+ nff->thisindex = idx;
+ /* constant type */
+ nff->tag = t;
+
+ if (!check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* class or interface type that contains the declaration of the
+ field or method */
+ nff->class_index = suck_u2(cb);
+
+ /* name and descriptor of the field or method */
+ nff->nameandtype_index = suck_u2(cb);
+
+ idx++;
+ break;
+
case CONSTANT_Integer: {
constant_integer *ci = NEW(constant_integer);
-#ifdef STATISTICS
- count_const_pool_len += sizeof(constant_integer);
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_integer);
#endif
+ if (!check_classbuffer_size(cb, 4))
+ return false;
+
ci->value = suck_s4(cb);
cptags[idx] = CONSTANT_Integer;
cpinfos[idx] = ci;
case CONSTANT_Float: {
constant_float *cf = NEW(constant_float);
-#ifdef STATISTICS
- count_const_pool_len += sizeof(constant_float);
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_float);
#endif
+ if (!check_classbuffer_size(cb, 4))
+ return false;
+
cf->value = suck_float(cb);
cptags[idx] = CONSTANT_Float;
cpinfos[idx] = cf;
case CONSTANT_Long: {
constant_long *cl = NEW(constant_long);
-#ifdef STATISTICS
- count_const_pool_len += sizeof(constant_long);
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_long);
#endif
+ if (!check_classbuffer_size(cb, 8))
+ return false;
+
cl->value = suck_s8(cb);
cptags[idx] = CONSTANT_Long;
cpinfos[idx] = cl;
idx += 2;
- if (idx > cpcount)
- panic("Long constant exceeds constant pool");
+ if (idx > cpcount) {
+ *exceptionptr =
+ new_classformaterror(c, "Invalid constant pool entry");
+ return false;
+ }
break;
}
case CONSTANT_Double: {
constant_double *cd = NEW(constant_double);
-#ifdef STATISTICS
- count_const_pool_len += sizeof(constant_double);
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_double);
#endif
+ if (!check_classbuffer_size(cb, 8))
+ return false;
+
cd->value = suck_double(cb);
cptags[idx] = CONSTANT_Double;
cpinfos[idx] = cd;
idx += 2;
- if (idx > cpcount)
- panic("Double constant exceeds constant pool");
+ if (idx > cpcount) {
+ *exceptionptr =
+ new_classformaterror(c, "Invalid constant pool entry");
+ return false;
+ }
break;
}
case CONSTANT_Utf8: {
+ u4 length;
+
/* number of bytes in the bytes array (not string-length) */
- u4 length = suck_u2(cb);
+ if (!check_classbuffer_size(cb, 2))
+ return false;
+
+ length = suck_u2(cb);
cptags[idx] = CONSTANT_Utf8;
+
/* validate the string */
- ASSERT_LEFT(cb, length);
+ if (!check_classbuffer_size(cb, length))
+ return false;
+
if (opt_verify &&
- !is_valid_utf(cb->pos + 1, cb->pos + 1 + length)) {
+ !is_valid_utf((char *) (cb->pos + 1),
+ (char *) (cb->pos + 1 + length))) {
dolog("Invalid UTF-8 string (constant pool index %d)",idx);
panic("Invalid UTF-8 string");
}
/* insert utf-string into the utf-symboltable */
- cpinfos[idx] = utf_new_int(cb->pos + 1, length);
+ cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
- /* skip bytes of the string */
+ /* skip bytes of the string (buffer size check above) */
skip_nbytes(cb, length);
idx++;
break;
}
default:
- error("Unkown constant type: %d",(int) t);
+ *exceptionptr =
+ new_classformaterror(c, "Illegal constant pool type");
+ return false;
} /* end switch */
} /* end while */
cptags[forward_classes->thisindex] = CONSTANT_Class;
/* retrieve class from class-table */
- cpinfos[forward_classes->thisindex] = class_new(name);
+ if (opt_eager) {
+ classinfo *tc;
+ tc = class_new_intern(name);
+
+ if (!class_load(tc))
+ return false;
+
+ /* link the class later, because we cannot link the class currently
+ loading */
+ list_addfirst(&unlinkedclasses, tc);
+
+ cpinfos[forward_classes->thisindex] = tc;
+
+ } else {
+ cpinfos[forward_classes->thisindex] = class_new(name);
+ }
+ nfc = forward_classes;
forward_classes = forward_classes->next;
+ FREE(nfc, forward_class);
}
while (forward_strings) {
utf *text =
class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
- /* resolve utf-string */
+ /* resolve utf-string */
cptags[forward_strings->thisindex] = CONSTANT_String;
cpinfos[forward_strings->thisindex] = text;
+ nfs = forward_strings;
forward_strings = forward_strings->next;
+ FREE(nfs, forward_string);
}
while (forward_nameandtypes) {
constant_nameandtype *cn = NEW(constant_nameandtype);
-#ifdef STATISTICS
- count_const_pool_len += sizeof(constant_nameandtype);
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_nameandtype);
#endif
/* resolve simple name and descriptor */
cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
cpinfos[forward_nameandtypes->thisindex] = cn;
-
+
+ nfn = forward_nameandtypes;
forward_nameandtypes = forward_nameandtypes->next;
+ FREE(nfn, forward_nameandtype);
}
while (forward_fieldmethints) {
constant_nameandtype *nat;
constant_FMIref *fmi = NEW(constant_FMIref);
-#ifdef STATISTICS
- count_const_pool_len += sizeof(constant_FMIref);
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_FMIref);
#endif
/* resolve simple name and descriptor */
nat = class_getconstant(c,
break;
case CONSTANT_InterfaceMethodref:
case CONSTANT_Methodref: /* check validity of descriptor */
- checkmethoddescriptor(fmi->descriptor);
+ checkmethoddescriptor(c, fmi->descriptor);
break;
}
+ nff = forward_fieldmethints;
forward_fieldmethints = forward_fieldmethints->next;
+ FREE(nff, forward_fieldmethint);
}
- dump_release(dumpsize);
+ /* everything was ok */
+
+ return true;
}
{
classbuffer *cb;
classinfo *r;
- s8 starttime;
- s8 stoptime;
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
- compiler_lock();
- tables_lock();
-#else
- intsDisable();
-#endif
-#endif
+ /* enter a monitor on the class */
+
+ builtin_monitorenter((java_objectheader *) c);
/* maybe the class is already loaded */
if (c->loaded) {
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
- tables_unlock();
- compiler_unlock();
-#else
- intsRestore();
-#endif
-#endif
+ builtin_monitorexit((java_objectheader *) c);
return c;
}
/* measure time */
+
+ if (getcompilingtime)
+ compilingtime_stop();
+
if (getloadingtime)
- starttime = getcputime();
+ loadingtime_start();
/* load classdata, throw exception on error */
new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
c->name);
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
- tables_unlock();
- compiler_unlock();
-#else
- intsRestore();
-#endif
-#endif
+ builtin_monitorexit((java_objectheader *) c);
return NULL;
}
r = class_load_intern(cb);
/* if return value is NULL, we had a problem and the class is not loaded */
- if (!r)
+ if (!r) {
c->loaded = false;
+ /* now free the allocated memory, otherwise we could ran into a DOS */
+ class_remove(c);
+ }
+
/* free memory */
suck_stop(cb);
/* measure time */
- if (getloadingtime) {
- stoptime = getcputime();
- loadingtime += (stoptime - starttime);
- }
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
- tables_unlock();
- compiler_unlock();
-#else
- intsRestore();
-#endif
-#endif
+ if (getloadingtime)
+ loadingtime_stop();
+
+ if (getcompilingtime)
+ compilingtime_start();
+
+ /* leave the monitor */
+
+ builtin_monitorexit((java_objectheader *) c);
return r;
}
classinfo *class_load_intern(classbuffer *cb)
{
classinfo *c;
+ classinfo *tc;
u4 i;
- u4 mi, ma;
- s4 classdata_left;
+ u4 ma, mi;
char msg[MAXLOGTEXT]; /* maybe we get an exception */
/* get the classbuffer's class */
if (c->loaded)
return c;
-#ifdef STATISTICS
- count_class_loads++;
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_class_loads++;
#endif
/* output for debugging purposes */
/* class is somewhat loaded */
c->loaded = true;
+ if (!check_classbuffer_size(cb, 4 + 2 + 2))
+ return NULL;
+
/* check signature */
if (suck_u4(cb) != MAGIC) {
- utf_sprint_classname(msg, c->name);
- sprintf(msg + strlen(msg), " (Bad magic number)");
-
- *exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError, msg);
+ *exceptionptr = new_classformaterror(c, "Bad magic number");
return NULL;
}
mi = suck_u2(cb);
ma = suck_u2(cb);
- if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION + 1 || mi != 0)) {
- utf_sprint_classname(msg, c->name);
- sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
- ma, mi);
-
+ if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError,
- msg);
+ new_unsupportedclassversionerror(c,
+ "Unsupported major.minor version %d.%d",
+ ma, mi);
return NULL;
}
- class_loadcpool(cb, c);
+ /* load the constant pool */
+ if (!class_loadcpool(cb, c))
+ return NULL;
+
/*JOWENN*/
c->erroneous_state = 0;
c->initializing_thread = 0;
c->impldBy = NULL;
/* ACC flags */
- c->flags = suck_u2(cb);
+ if (!check_classbuffer_size(cb, 2))
+ return NULL;
+
+ c->flags = suck_u2(cb);
/*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
/* check ACC flags consistency */
}
if (c->flags & ACC_FINAL) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg),
- " (Illegal class modifiers: 0x%x)", c->flags);
-
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError, msg);
+ new_classformaterror(c,
+ "Illegal class modifiers: 0x%X", c->flags);
return NULL;
}
}
if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg),
- " (Illegal class modifiers: 0x%x)", c->flags);
-
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError, msg);
+ new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
return NULL;
}
+ if (!check_classbuffer_size(cb, 2 + 2))
+ return NULL;
+
/* this class */
i = suck_u2(cb);
- if (class_getconstant(c, i, CONSTANT_Class) != c) {
+ if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
+ return NULL;
+
+ if (tc != c) {
utf_sprint(msg, c->name);
sprintf(msg + strlen(msg), " (wrong name: ");
- utf_sprint(msg + strlen(msg),
- ((classinfo *) class_getconstant(c, i, CONSTANT_Class))->name);
+ utf_sprint(msg + strlen(msg), tc->name);
sprintf(msg + strlen(msg), ")");
*exceptionptr =
/* retrieve superclass */
if ((i = suck_u2(cb))) {
- c->super = class_getconstant(c, i, CONSTANT_Class);
+ if (!(c->super = class_getconstant(c, i, CONSTANT_Class)))
+ return NULL;
/* java.lang.Object may not have a super class. */
if (c->name == utf_java_lang_Object) {
/* This is only allowed for java.lang.Object. */
if (c->name != utf_java_lang_Object) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg), " (Bad superclass index)");
-
- *exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError, msg);
+ *exceptionptr = new_classformaterror(c, "Bad superclass index");
return NULL;
}
-
}
/* retrieve interfaces */
+ if (!check_classbuffer_size(cb, 2))
+ return NULL;
+
c->interfacescount = suck_u2(cb);
+
+ if (!check_classbuffer_size(cb, 2 * c->interfacescount))
+ return NULL;
+
c->interfaces = MNEW(classinfo*, c->interfacescount);
for (i = 0; i < c->interfacescount; i++) {
- c->interfaces[i] =
- class_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+ return NULL;
}
/* load fields */
+ if (!check_classbuffer_size(cb, 2))
+ return NULL;
+
c->fieldscount = suck_u2(cb);
c->fields = GCNEW(fieldinfo, c->fieldscount);
/* c->fields = MNEW(fieldinfo, c->fieldscount); */
}
/* load methods */
+ if (!check_classbuffer_size(cb, 2))
+ return NULL;
+
c->methodscount = suck_u2(cb);
c->methods = GCNEW(methodinfo, c->methodscount);
/* c->methods = MNEW(methodinfo, c->methodscount); */
/* Check fields */
memset(hashtab, 0, sizeof(u2) * (hashlen + len));
+
for (i = 0; i < c->fieldscount; ++i) {
fieldinfo *fi = c->fields + i;
+
/* It's ok if we lose bits here */
index = ((((size_t) fi->name) +
((size_t) fi->descriptor)) >> shift) % hashlen;
+
if ((old = hashtab[index])) {
old--;
next[i] = old;
do {
if (c->fields[old].name == fi->name &&
c->fields[old].descriptor == fi->descriptor) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg), " (Repetitive field name/signature)");
-
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError,
- msg);
+ new_classformaterror(c,
+ "Repetitive field name/signature");
return NULL;
}
}
/* Check methods */
- memset(hashtab, 0, sizeof(u2) * (hashlen + len));
+ memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
+
for (i = 0; i < c->methodscount; ++i) {
methodinfo *mi = c->methods + i;
+
/* It's ok if we lose bits here */
index = ((((size_t) mi->name) +
((size_t) mi->descriptor)) >> shift) % hashlen;
+
+ /*{ JOWENN
+ int dbg;
+ for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
+ printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
+ }
+ }*/
+
if ((old = hashtab[index])) {
old--;
next[i] = old;
do {
if (c->methods[old].name == mi->name &&
c->methods[old].descriptor == mi->descriptor) {
- utf_sprint(msg, c->name);
- sprintf(msg + strlen(msg), " (Repetitive method name/signature)");
-
*exceptionptr =
- new_exception_message(string_java_lang_ClassFormatError,
- msg);
+ new_classformaterror(c,
+ "Repetitive method name/signature");
return NULL;
}
MFREE(hashtab, u2, (hashlen + len));
}
-#ifdef STATISTICS
+#if defined(STATISTICS)
if (opt_stat) {
count_class_infos += sizeof(classinfo*) * c->interfacescount;
count_class_infos += sizeof(fieldinfo) * c->fieldscount;
}
#endif
- /* load variable-length attribute structures */
- attribute_load(cb, c, suck_u2(cb));
+ /* load attribute structures */
+ if (!check_classbuffer_size(cb, 2))
+ return NULL;
+
+ if (!attribute_load(cb, c, suck_u2(cb)))
+ return NULL;
#if 0
- /* XXX TWISTI is this still in the JVM spec? SUN and IBM don't complain about it */
-
- /* check if all data has been read */
- classdata_left = ((cb->data + cb->size) - cb->pos - 1);
-
- if (classdata_left > 0) {
- /* surplus */
- dolog("There are %d extra bytes at end of classfile", classdata_left);
- /* The JVM spec disallows extra bytes. */
- panic("Extra bytes at end of classfile");
+ /* Pre java 1.5 version don't check this. This implementation is like
+ java 1.5 do it: for class file version 45.3 we don't check it, older
+ versions are checked.
+ */
+ if ((ma == 45 && mi > 3) || ma > 45) {
+ /* check if all data has been read */
+ s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
+
+ if (classdata_left > 0) {
+ *exceptionptr =
+ new_classformaterror(c, "Extra bytes at the end of class file");
+ return NULL;
+ }
}
#endif
s4 h;
s4 i;
- if (!(c->flags & ACC_INTERFACE)) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "Interface-methods count requested for non-interface: ");
- utf_sprint(logtext + strlen(logtext), c->name);
- error("%s",logtext);
- }
-
+ /* check for ACC_INTERFACE bit already done in class_link_intern */
+
h = c->index;
for (i = 0; i < c->interfacescount; i++) {
s4 h2 = class_highestinterface(c->interfaces[i]);
/* class_addinterface **********************************************************
- Is needed by class_link for adding a VTBL to a class. All interfaces
- implemented by ic are added as well.
+ Is needed by class_link for adding a VTBL to a class. All interfaces
+ implemented by ic are added as well.
*******************************************************************************/
static void class_addinterface(classinfo *c, classinfo *ic)
{
s4 j, m;
- s4 i = ic->index;
- vftbl *vftbl = c->vftbl;
+ s4 i = ic->index;
+ vftbl_t *v = c->vftbl;
- if (i >= vftbl->interfacetablelength)
+ if (i >= v->interfacetablelength)
panic ("Inernal error: interfacetable overflow");
- if (vftbl->interfacetable[-i])
+ if (v->interfacetable[-i])
return;
if (ic->methodscount == 0) { /* fake entry needed for subtype test */
- vftbl->interfacevftbllength[i] = 1;
- vftbl->interfacetable[-i] = MNEW(methodptr, 1);
- vftbl->interfacetable[-i][0] = NULL;
+ v->interfacevftbllength[i] = 1;
+ v->interfacetable[-i] = MNEW(methodptr, 1);
+ v->interfacetable[-i][0] = NULL;
} else {
- vftbl->interfacevftbllength[i] = ic->methodscount;
- vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
+ v->interfacevftbllength[i] = ic->methodscount;
+ v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
-#ifdef STATISTICS
+#if defined(STATISTICS)
if (opt_stat)
count_vftbl_len += sizeof(methodptr) *
(ic->methodscount + (ic->methodscount == 0));
for (m = 0; m < sc->methodscount; m++) {
methodinfo *mi = &(sc->methods[m]);
if (method_canoverwrite(mi, &(ic->methods[j]))) {
- vftbl->interfacetable[-i][j] =
- vftbl->table[mi->vftblindex];
+ v->interfacetable[-i][j] = v->table[mi->vftblindex];
goto foundmethod;
}
}
/* Check the component type */
switch (c->name->text[1]) {
- case '[':
- /* c is an array of arrays. We have to create the component class. */
- comp = class_new(utf_new_int(c->name->text + 1, namelen - 1));
- break;
+ case '[':
+ /* c is an array of arrays. We have to create the component class. */
+ if (opt_eager) {
+ comp = class_new_intern(utf_new_intern(c->name->text + 1,
+ namelen - 1));
+ class_load(comp);
+ list_addfirst(&unlinkedclasses, comp);
- case 'L':
- /* c is an array of objects. */
- if (namelen < 4 || c->name->text[namelen - 1] != ';')
- panic("Invalid array class name");
- comp = class_new(utf_new_int(c->name->text + 2, namelen - 3));
- break;
+ } else {
+ comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
+ }
+ break;
+
+ case 'L':
+ /* c is an array of objects. */
+ if (namelen < 4 || c->name->text[namelen - 1] != ';')
+ panic("Invalid array class name");
+
+ if (opt_eager) {
+ comp = class_new_intern(utf_new_intern(c->name->text + 2,
+ namelen - 3));
+ class_load(comp);
+ list_addfirst(&unlinkedclasses, comp);
+
+ } else {
+ comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
+ }
+ break;
}
/* Setup the array class */
c->interfacescount = 2;
c->interfaces = MNEW(classinfo*, 2);
- c->interfaces[0] = class_new(utf_new_char("java/lang/Cloneable"));
- c->interfaces[1] = class_new(utf_new_char("java/io/Serializable"));
+
+ if (opt_eager) {
+ classinfo *tc;
+
+ tc = class_new_intern(utf_new_char("java/lang/Cloneable"));
+ class_load(tc);
+ list_addfirst(&unlinkedclasses, tc);
+ c->interfaces[0] = tc;
+
+ tc = class_new_intern(utf_new_char("java/io/Serializable"));
+ class_load(tc);
+ list_addfirst(&unlinkedclasses, tc);
+ c->interfaces[1] = tc;
+
+ } else {
+ c->interfaces[0] = class_new(utf_new_char("java/lang/Cloneable"));
+ c->interfaces[1] = class_new(utf_new_char("java/io/Serializable"));
+ }
c->methodscount = 1;
c->methods = MNEW(methodinfo, c->methodscount);
classinfo *comp = NULL;
s4 namelen = c->name->blength;
arraydescriptor *desc;
- vftbl *compvftbl;
+ vftbl_t *compvftbl;
/* Check the component type */
switch (c->name->text[1]) {
case '[':
/* c is an array of arrays. */
-/* comp = class_get(utf_new_int(c->name->text + 1, namelen - 1)); */
- comp = class_new(utf_new_int(c->name->text + 1, namelen - 1));
+ comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
if (!comp)
panic("Could not find component array class.");
break;
case 'L':
/* c is an array of objects. */
-/* comp = class_get(utf_new_int(c->name->text + 2, namelen - 3)); */
- comp = class_new(utf_new_int(c->name->text + 2, namelen - 3));
+ comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
if (!comp)
panic("Could not find component class.");
break;
/* If the component type has not been linked, link it now */
if (comp && !comp->linked) {
if (!comp->loaded)
- class_load(comp);
- class_link(comp);
+ if (!class_load(comp))
+ return NULL;
+
+ if (!class_link(comp))
+ return NULL;
}
/* Allocate the arraydescriptor */
classinfo *class_link(classinfo *c)
{
classinfo *r;
- s8 starttime;
- s8 stoptime;
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
- compiler_lock();
- tables_lock();
-#else
- intsDisable();
-#endif
-#endif
+ /* enter a monitor on the class */
+
+ builtin_monitorenter((java_objectheader *) c);
/* maybe the class is already linked */
if (c->linked) {
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
- tables_unlock();
- compiler_unlock();
-#else
- intsRestore();
-#endif
-#endif
+ builtin_monitorexit((java_objectheader *) c);
return c;
}
/* measure time */
+
+ if (getcompilingtime)
+ compilingtime_stop();
+
if (getloadingtime)
- starttime = getcputime();
+ loadingtime_start();
/* call the internal function */
r = class_link_intern(c);
c->linked = false;
/* measure time */
- if (getloadingtime) {
- stoptime = getcputime();
- loadingtime += (stoptime - starttime);
- }
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
- tables_unlock();
- compiler_unlock();
-#else
- intsRestore();
-#endif
-#endif
- if (c->linked) return c; else return 0;
+ if (getloadingtime)
+ loadingtime_stop();
+
+ if (getcompilingtime)
+ compilingtime_start();
+
+ /* leave the monitor */
+
+ builtin_monitorexit((java_objectheader *) c);
+
+ return r;
}
s4 supervftbllength; /* vftbllegnth of super class */
s4 vftbllength; /* vftbllength of current class */
s4 interfacetablelength; /* interface table length */
- classinfo *super = c->super; /* super class */
- classinfo *ic, *c2; /* intermediate class variables */
- vftbl *v; /* vftbl of current class */
+ classinfo *super; /* super class */
+ classinfo *tc; /* temporary class variable */
+ vftbl_t *v; /* vftbl of current class */
s4 i; /* interface/method/field counter */
- arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
+ arraydescriptor *arraydesc; /* descriptor for array classes */
/* maybe the class is already linked */
if (c->linked)
return c;
+ /* maybe the class is not loaded */
+ if (!c->loaded)
+ if (!class_load(c))
+ return NULL;
+
if (linkverbose)
log_message_class("Linking class: ", c);
/* ok, this class is somewhat linked */
c->linked = true;
+ arraydesc = NULL;
+
/* check interfaces */
for (i = 0; i < c->interfacescount; i++) {
- ic = c->interfaces[i];
+ tc = c->interfaces[i];
/* detect circularity */
- if (ic == c) {
+ if (tc == c) {
*exceptionptr =
new_exception_utfmessage(string_java_lang_ClassCircularityError,
c->name);
-
return NULL;
}
- if (!ic->loaded)
- class_load(ic);
-
- if (!ic->linked)
- class_link(ic);
+ if (!tc->loaded)
+ if (!class_load(tc))
+ return NULL;
- if (!(ic->flags & ACC_INTERFACE)) {
- dolog("Specified interface is not declared as interface:");
- log_utf(ic->name);
- dolog("in");
- log_utf(c->name);
- panic("Specified interface is not declared as interface");
+ if (!(tc->flags & ACC_INTERFACE)) {
+ *exceptionptr =
+ new_exception_message(string_java_lang_IncompatibleClassChangeError,
+ "Implementing class");
+ return NULL;
}
+
+ if (!tc->linked)
+ if (!class_link(tc))
+ return NULL;
}
- /* check super class */
+ /* check super class */
+
+ super = c->super;
if (super == NULL) { /* class java.lang.Object */
c->index = 0;
*exceptionptr =
new_exception_utfmessage(string_java_lang_ClassCircularityError,
c->name);
-
return NULL;
}
if (!super->loaded)
- class_load(super);
-
- if (!super->linked)
- class_link(super);
+ if (!class_load(super))
+ return NULL;
- if (super->flags & ACC_INTERFACE)
+ if (super->flags & ACC_INTERFACE) {
+ /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
panic("Interface specified as super class");
-
- /* handle array classes */
- /* The component class must have been linked already. */
- if (c->name->text[0] == '[') {
- if ((arraydesc = class_link_array(c)) == NULL) {
- panic("class_link: class_link_array");
- }
}
/* Don't allow extending final classes */
- if (super->flags & ACC_FINAL)
- panic("Trying to extend final class");
+ if (super->flags & ACC_FINAL) {
+ *exceptionptr =
+ new_exception_message(string_java_lang_VerifyError,
+ "Cannot inherit from final class");
+ return NULL;
+ }
+ if (!super->linked)
+ if (!class_link(super))
+ return NULL;
+
+ /* handle array classes */
+ if (c->name->text[0] == '[')
+ if (!(arraydesc = class_link_array(c)))
+ return NULL;
+
if (c->flags & ACC_INTERFACE)
c->index = interfaceindex++;
else
methodinfo *m = &(c->methods[i]);
if (!(m->flags & ACC_STATIC)) { /* is instance method */
- classinfo *sc = super;
- while (sc) {
+ tc = super;
+
+ while (tc) {
s4 j;
- for (j = 0; j < sc->methodscount; j++) {
- if (method_canoverwrite(m, &(sc->methods[j]))) {
- if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
+ for (j = 0; j < tc->methodscount; j++) {
+ if (method_canoverwrite(m, &(tc->methods[j]))) {
+ if (tc->methods[j].flags & ACC_PRIVATE)
goto notfoundvftblindex;
- if ((sc->methods[j].flags & ACC_FINAL) != 0) {
- log_utf(c->name);
- log_utf(sc->name);
- log_utf(sc->methods[j].name);
- log_utf(sc->methods[j].descriptor);
- panic("Trying to overwrite final method");
+ if (tc->methods[j].flags & ACC_FINAL) {
+ /* class a overrides final method . */
+ *exceptionptr =
+ new_exception(string_java_lang_VerifyError);
+ return NULL;
}
- m->vftblindex = sc->methods[j].vftblindex;
+ m->vftblindex = tc->methods[j].vftblindex;
goto foundvftblindex;
}
}
- sc = sc->super;
+ tc = tc->super;
}
notfoundvftblindex:
m->vftblindex = (vftbllength++);
}
}
-#ifdef STATISTICS
+#if defined(STATISTICS)
if (opt_stat)
count_vftbl_len +=
- sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
+ sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
#endif
/* compute interfacetable length */
interfacetablelength = 0;
- c2 = c;
- while (c2) {
- for (i = 0; i < c2->interfacescount; i++) {
- s4 h = class_highestinterface(c2->interfaces[i]) + 1;
+ tc = c;
+ while (tc) {
+ for (i = 0; i < tc->interfacescount; i++) {
+ s4 h = class_highestinterface(tc->interfaces[i]) + 1;
if (h > interfacetablelength)
interfacetablelength = h;
}
- c2 = c2->super;
+ tc = tc->super;
}
/* allocate virtual function table */
- v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
+ v = (vftbl_t*) mem_alloc(sizeof(vftbl_t) + sizeof(methodptr) *
(vftbllength - 1) + sizeof(methodptr*) *
(interfacetablelength - (interfacetablelength > 0)));
- v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
+ v = (vftbl_t*) (((methodptr*) v) + (interfacetablelength - 1) *
(interfacetablelength > 1));
c->header.vftbl = c->vftbl = v;
-/* utf_display_classname(c->name);printf(", c->header.vftbl=%p\n", c->header.vftbl); */
v->class = c;
v->vftbllength = vftbllength;
v->interfacetablelength = interfacetablelength;
- v->arraydesc = arraydesc;
+ v->arraydesc = arraydesc;
/* store interface index in vftbl */
if (c->flags & ACC_INTERFACE)
v->interfacevftbllength = MNEW(s4, interfacetablelength);
-#ifdef STATISTICS
+#if defined(STATISTICS)
if (opt_stat)
count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
#endif
/* add interfaces */
- for (c2 = c; c2 != NULL; c2 = c2->super)
- for (i = 0; i < c2->interfacescount; i++) {
- class_addinterface(c, c2->interfaces[i]);
+ for (tc = c; tc != NULL; tc = tc->super) {
+ for (i = 0; i < tc->interfacescount; i++) {
+ class_addinterface(c, tc->interfaces[i]);
}
+ }
/* add finalizer method (not for java.lang.Object) */
- if (super != NULL) {
+ if (super) {
methodinfo *fi;
- static utf *finame = NULL;
- static utf *fidesc = NULL;
- if (finame == NULL)
- finame = utf_finalize;
- if (fidesc == NULL)
- fidesc = utf_fidesc;
+ fi = class_findmethod(c, utf_finalize, utf_fidesc);
- fi = class_findmethod(c, finame, fidesc);
- if (fi != NULL) {
+ if (fi) {
if (!(fi->flags & ACC_STATIC)) {
c->finalizer = fi;
}
u4 tag;
voidptr info;
- for (idx=0; idx < c->cpcount; idx++) {
- tag = c->cptags[idx];
- info = c->cpinfos[idx];
+ if (c->cptags && c->cpinfos) {
+ for (idx = 0; idx < c->cpcount; idx++) {
+ tag = c->cptags[idx];
+ info = c->cpinfos[idx];
- if (info != NULL) {
- switch (tag) {
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- FREE(info, constant_FMIref);
- break;
- case CONSTANT_Integer:
- FREE(info, constant_integer);
- break;
- case CONSTANT_Float:
- FREE(info, constant_float);
- break;
- case CONSTANT_Long:
- FREE(info, constant_long);
- break;
- case CONSTANT_Double:
- FREE(info, constant_double);
- break;
- case CONSTANT_NameAndType:
- FREE(info, constant_nameandtype);
- break;
+ if (info != NULL) {
+ switch (tag) {
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ FREE(info, constant_FMIref);
+ break;
+ case CONSTANT_Integer:
+ FREE(info, constant_integer);
+ break;
+ case CONSTANT_Float:
+ FREE(info, constant_float);
+ break;
+ case CONSTANT_Long:
+ FREE(info, constant_long);
+ break;
+ case CONSTANT_Double:
+ FREE(info, constant_double);
+ break;
+ case CONSTANT_NameAndType:
+ FREE(info, constant_nameandtype);
+ break;
+ }
}
}
}
- MFREE(c->cptags, u1, c->cpcount);
- MFREE(c->cpinfos, voidptr, c->cpcount);
+ if (c->cptags)
+ MFREE(c->cptags, u1, c->cpcount);
+
+ if (c->cpinfos)
+ MFREE(c->cpinfos, voidptr, c->cpcount);
}
*******************************************************************************/
-static void class_free(classinfo *c)
+void class_free(classinfo *c)
{
s4 i;
- vftbl *v;
+ vftbl_t *v;
class_freecpool(c);
- MFREE(c->interfaces, classinfo*, c->interfacescount);
+ if (c->interfaces)
+ MFREE(c->interfaces, classinfo*, c->interfacescount);
- for (i = 0; i < c->fieldscount; i++)
- field_free(&(c->fields[i]));
+ if (c->fields) {
+ for (i = 0; i < c->fieldscount; i++)
+ field_free(&(c->fields[i]));
+/* MFREE(c->fields, fieldinfo, c->fieldscount); */
+ }
- for (i = 0; i < c->methodscount; i++)
- method_free(&(c->methods[i]));
- MFREE(c->methods, methodinfo, c->methodscount);
+ if (c->methods) {
+ for (i = 0; i < c->methodscount; i++)
+ method_free(&(c->methods[i]));
+/* MFREE(c->methods, methodinfo, c->methodscount); */
+ }
if ((v = c->vftbl) != NULL) {
if (v->arraydesc)
}
MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
- i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
+ i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
sizeof(methodptr*) * (v->interfacetablelength -
(v->interfacetablelength > 0));
- v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
+ v = (vftbl_t*) (((methodptr*) v) - (v->interfacetablelength - 1) *
(v->interfacetablelength > 1));
mem_free(v, i);
}
- if (c->innerclasscount)
+ if (c->innerclass)
MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
/* if (c->classvftbl)
methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
{
+ /*log_text("Trying to resolve a method");
+ utf_display(c->name);
+ utf_display(name);
+ utf_display(desc);*/
+
while (c) {
+ /*log_text("Looking in:");
+ utf_display(c->name);*/
methodinfo *m = class_findmethod(c, name, desc);
if (m) return m;
/* search superclass */
c = c->super;
}
+ /*log_text("method not found:");*/
return NULL;
}
*******************************************************************************/
+static classinfo *class_init_intern(classinfo *c);
+
classinfo *class_init(classinfo *c)
{
- methodinfo *m;
- s4 i;
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
- int b;
-#endif
+ classinfo *r;
if (!makeinitializations)
return c;
- if (c->initialized)
+ /* enter a monitor on the class */
+
+ builtin_monitorenter((java_objectheader *) c);
+
+ /* maybe the class is already initalized or the current thread, which can
+ pass the monitor, is currently initalizing this class */
+
+ if (c->initialized || c->initializing) {
+ builtin_monitorexit((java_objectheader *) c);
+
return c;
+ }
+
+ /* this initalizing run begins NOW */
+ c->initializing = true;
+
+ /* call the internal function */
+ r = class_init_intern(c);
+
+ /* if return value is not NULL everything was ok and the class is
+ initialized */
+ if (r)
+ c->initialized = true;
+
+ /* this initalizing run is done */
+ c->initializing = false;
+
+ /* leave the monitor */
- /* class is somewhat initialized */
- c->initialized = true;
+ builtin_monitorexit((java_objectheader *) c);
+
+ return r;
+}
+
+
+/* this function MUST NOT be called directly, because of thread <clinit>
+ race conditions */
+
+static classinfo *class_init_intern(classinfo *c)
+{
+ methodinfo *m;
+ s4 i;
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
+ int b;
+#endif
+ /* maybe the class is not already loaded */
if (!c->loaded)
if (!class_load(c))
return NULL;
+ /* maybe the class is not already linked */
if (!c->linked)
if (!class_link(c))
return NULL;
#endif
/* initialize super class */
- if (c->super) {
- if (!c->super->loaded)
- if (!class_load(c->super))
- return NULL;
-
- if (!c->super->linked)
- if (!class_link(c->super))
- return NULL;
+ if (c->super) {
if (!c->super->initialized) {
if (initverbose) {
char logtext[MAXLOGTEXT];
}
/* initialize interface classes */
- for (i = 0; i < c->interfacescount; i++) {
- if (!c->interfaces[i]->loaded)
- if (!class_load(c->interfaces[i]))
- return NULL;
-
- if (!c->interfaces[i]->linked)
- if (!class_link(c->interfaces[i]))
- return NULL;
+ for (i = 0; i < c->interfacescount; i++) {
if (!c->interfaces[i]->initialized) {
if (initverbose) {
char logtext[MAXLOGTEXT];
return c;
}
- if (!(m->flags & ACC_STATIC))
- panic("Class initializer is not static!");
+ /* Sun's and IBM's JVM don't care about the static flag */
+/* if (!(m->flags & ACC_STATIC)) { */
+/* panic("Class initializer is not static!"); */
if (initverbose)
log_message_class("Starting static class initializer for class: ", c);
blockInts = b;
#endif
- /* we have an exception */
+ /* we have an exception or error */
if (*exceptionptr) {
- java_objectheader *xptr;
- java_objectheader *cause;
-
/* class is NOT initialized */
c->initialized = false;
- /* get the cause */
- cause = *exceptionptr;
+ /* is this an exception, than wrap it */
+ if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
+ java_objectheader *xptr;
+ java_objectheader *cause;
- /* clear exception, because we are calling jit code again */
- *exceptionptr = NULL;
+ /* get the cause */
+ cause = *exceptionptr;
- /* wrap the exception */
- xptr =
- new_exception_throwable(string_java_lang_ExceptionInInitializerError,
- (java_lang_Throwable *) cause);
+ /* clear exception, because we are calling jit code again */
+ *exceptionptr = NULL;
- if (*exceptionptr) {
- panic("problem");
- }
+ /* wrap the exception */
+ xptr =
+ new_exception_throwable(string_java_lang_ExceptionInInitializerError,
+ (java_lang_Throwable *) cause);
+
+ /* XXX should we exit here? */
+ if (*exceptionptr)
+ throw_exception();
- /* set new exception */
- *exceptionptr = xptr;
+ /* set new exception */
+ *exceptionptr = xptr;
+ }
return NULL;
}
*******************************************************************************/
-void create_primitive_classes()
+static bool create_primitive_classes()
{
- int i;
+ s4 i;
for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
/* create primitive class */
- classinfo *c = class_new_int(utf_new_char(primitivetype_table[i].name));
+ classinfo *c =
+ class_new_intern(utf_new_char(primitivetype_table[i].name));
c->classUsed = NOTUSED; /* not used initially CO-RT */
c->impldBy = NULL;
/* prevent loader from loading primitive class */
c->loaded = true;
- class_link(c);
+ if (!class_link(c))
+ return false;
primitivetype_table[i].class_primitive = c;
/* create class for wrapping the primitive type */
- c = class_new_int(utf_new_char(primitivetype_table[i].wrapname));
+ c = class_new_intern(utf_new_char(primitivetype_table[i].wrapname));
primitivetype_table[i].class_wrap = c;
primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
primitivetype_table[i].class_wrap->impldBy = NULL;
/* create the primitive array class */
if (primitivetype_table[i].arrayname) {
- c = class_new_int(utf_new_char(primitivetype_table[i].arrayname));
+ c = class_new_intern(utf_new_char(primitivetype_table[i].arrayname));
primitivetype_table[i].arrayclass = c;
c->loaded = true;
if (!c->linked)
- class_link(c);
+ if (!class_link(c))
+ return false;
primitivetype_table[i].arrayvftbl = c->vftbl;
}
}
+
+ return true;
}
* CLASSLOAD_PANIC....abort execution with an error message
CLASSLOAD_NOPANIC..return NULL on error
-********************************************************************************/
+*******************************************************************************/
classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
char **next, int mode)
case '[':
if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
name = utf_new(start, utf_ptr - start);
- return (mode & CLASSLOAD_LOAD)
- ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
+ if (opt_eager) {
+ classinfo *tc;
+
+ tc = class_new_intern(name);
+ class_load(tc);
+ list_addfirst(&unlinkedclasses, tc);
+
+ return tc;
+
+ } else {
+ return (mode & CLASSLOAD_LOAD)
+ ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
+ }
}
}
{
/* pseudo class for Arraystubs (extends java.lang.Object) */
- pseudo_class_Arraystub = class_new_int(utf_new_char("$ARRAYSTUB$"));
+ pseudo_class_Arraystub = class_new_intern(utf_new_char("$ARRAYSTUB$"));
pseudo_class_Arraystub->loaded = true;
pseudo_class_Arraystub->super = class_java_lang_Object;
pseudo_class_Arraystub->interfacescount = 2;
/* pseudo class representing the null type */
- pseudo_class_Null = class_new_int(utf_new_char("$NULL$"));
+ pseudo_class_Null = class_new_intern(utf_new_char("$NULL$"));
pseudo_class_Null->loaded = true;
pseudo_class_Null->super = class_java_lang_Object;
class_link(pseudo_class_Null);
/* pseudo class representing new uninitialized objects */
- pseudo_class_New = class_new_int(utf_new_char("$NEW$"));
+ pseudo_class_New = class_new_intern(utf_new_char("$NEW$"));
pseudo_class_New->loaded = true;
pseudo_class_New->linked = true;
pseudo_class_New->super = class_java_lang_Object;
utf_vmclass = utf_new_char("java/lang/VMClass");
utf_java_lang_Object= utf_new_char("java/lang/Object");
array_packagename = utf_new_char("<the array package>");
+ utf_fillInStackTrace_name = utf_new_char("fillInStackTrace");
+ utf_fillInStackTrace_desc = utf_new_char("()Ljava/lang/Throwable;");
/* create some important classes */
/* These classes have to be created now because the classinfo
* pointers are used in the loading code.
*/
- class_java_lang_Object =
- class_new_int(utf_java_lang_Object);
+ class_java_lang_Object = class_new_intern(utf_java_lang_Object);
class_load(class_java_lang_Object);
class_link(class_java_lang_Object);
- class_java_lang_String =
- class_new_int(utf_new_char("java/lang/String"));
+ class_java_lang_String = class_new(utf_new_char("java/lang/String"));
class_load(class_java_lang_String);
class_link(class_java_lang_String);
- class_java_lang_Cloneable =
- class_new_int(utf_new_char("java/lang/Cloneable"));
+ class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
class_load(class_java_lang_Cloneable);
class_link(class_java_lang_Cloneable);
class_java_io_Serializable =
- class_new_int(utf_new_char("java/io/Serializable"));
+ class_new(utf_new_char("java/io/Serializable"));
class_load(class_java_io_Serializable);
class_link(class_java_io_Serializable);
}
-static void loader_compute_class_values(classinfo *c)
-{
- classinfo *subs;
-
- c->vftbl->baseval = ++classvalue;
+/* loader_compute_subclasses ***************************************************
- subs = c->sub;
- while (subs != NULL) {
- loader_compute_class_values(subs);
- subs = subs->nextsub;
- }
+ XXX
- c->vftbl->diffval = classvalue - c->vftbl->baseval;
-}
+*******************************************************************************/
+static void loader_compute_class_values(classinfo *c);
void loader_compute_subclasses(classinfo *c)
{
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+ compiler_lock();
+#else
intsDisable();
+#endif
#endif
if (!(c->flags & ACC_INTERFACE)) {
classvalue = 0;
/* this is the java.lang.Object special case */
+
if (!class_java_lang_Object) {
loader_compute_class_values(c);
loader_compute_class_values(class_java_lang_Object);
}
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+ compiler_unlock();
+#else
intsRestore();
#endif
+#endif
+}
+
+
+/* loader_compute_class_values *************************************************
+
+ XXX
+
+*******************************************************************************/
+
+static void loader_compute_class_values(classinfo *c)
+{
+ classinfo *subs;
+
+ c->vftbl->baseval = ++classvalue;
+
+ subs = c->sub;
+ while (subs) {
+ loader_compute_class_values(subs);
+ subs = subs->nextsub;
+ }
+
+ c->vftbl->diffval = classvalue - c->vftbl->baseval;
}
void loader_close()
{
-/* classinfo *c; */
+ classinfo *c;
+ s4 slot;
-/* while ((c = list_first(&unloadedclasses))) { */
-/* list_remove(&unloadedclasses, c); */
-/* class_free(c); */
-/* } */
-/* while ((c = list_first(&unlinkedclasses))) { */
-/* list_remove(&unlinkedclasses, c); */
-/* class_free(c); */
-/* } */
-/* while ((c = list_first(&linkedclasses))) { */
-/* list_remove(&linkedclasses, c); */
-/* class_free(c); */
-/* } */
+ for (slot = 0; slot < class_hash.size; slot++) {
+ c = class_hash.ptr[slot];
+
+ while (c) {
+ class_free(c);
+ c = c->hashlink;
+ }
+ }
}