Edwin Steiner
Christian Thalinger
- $Id: loader.c 1182 2004-06-19 12:13:45Z twisti $
+ $Id: loader.c 1553 2004-11-19 15:47:13Z carolyn $
*/
#include <string.h>
#include <assert.h>
#include <sys/stat.h>
+#include "exceptions.h"
#include "global.h"
#include "loader.h"
-#include "main.h"
+#include "options.h"
#include "native.h"
#include "tables.h"
#include "builtin.h"
#include "jit/jit.h"
#include "asmpart.h"
+#include "statistics.h"
#include "toolbox/memory.h"
#include "toolbox/logging.h"
#include "threads/thread.h"
/* 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;
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 */
-
-
-static java_objectheader *new_classformaterror(classinfo *c, char *message, ...)
-{
- char cfmessage[MAXLOGTEXT];
- va_list ap;
-
- utf_sprint_classname(cfmessage, c->name);
- sprintf(cfmessage + strlen(cfmessage), " (");
-
- va_start(ap, message);
- vsprintf(cfmessage + strlen(cfmessage), message, ap);
- va_end(ap);
-
- sprintf(cfmessage + strlen(cfmessage), ")");
-
- return new_exception_message(string_java_lang_ClassFormatError, cfmessage);
-}
-
-
/* check_classbuffer_size ******************************************************
assert that at least <len> bytes are left to read
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)
{
*******************************************************************************/
-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);
- filename = NULL;
}
}
}
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;
+ 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
- strcpy(filename + filenamelen, ".class");
- filenamelen += 6;
+ /* initialize return value */
- 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) {
+ cb = NULL;
+
+ 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 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 */
+#endif /* USE_ZLIB */
+
+ path = MNEW(char, cpi->filepath.pathlen + filenamelen + 1);
+ strcpy(path, cpi->filepath.path);
+ strcat(path, filename);
- /* determine size of classfile */
+ classfile = fopen(path, "r");
- /* dolog("File: %s",filename); */
- err = stat(currPos->filepath.filename, &buffer);
+ if (classfile) { /* file exists */
+ /* determine size of classfile */
+ err = stat(path, &buffer);
if (!err) { /* read classfile data */
cb = NEW(classbuffer);
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)) { */
+/* } */
+ }
}
}
-#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 (err)
+ dolog("Warning: Can not open class file '%s'", filename);
}
- return NULL;
+ MFREE(filename, char, filenamelen);
+
+ return cb;
}
}
+/******************** 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)
+{
+ /* 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];
+}
+
+
/******************** function: innerclass_getconstant ************************
like class_getconstant, but if cptags is ZERO null is returned
*******************************************************************************/
-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 bool attribute_load(classbuffer *cb, classinfo *c, u4 num)
{
+ utf *aname;
u4 i, j;
for (i = 0; i < num; i++) {
if (!check_classbuffer_size(cb, 2))
return false;
- utf *aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+ 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;
+ }
if (!check_classbuffer_size(cb, 4 + 2))
return false;
- /* skip attribute length */
+ /* skip attribute length */
suck_u4(cb);
/* number of records */
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
+ 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. */
info->flags = suck_u2(cb);
}
- } else if (aname==utf_sourcefile) {
+ } else if (aname == utf_sourcefile) {
if (!check_classbuffer_size(cb, 4 + 2))
return false;
- suck_u4(cb);
- c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+ 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 */
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 */
+ utf *u;
if (!check_classbuffer_size(cb, 2 + 2 + 2))
return false;
f->flags = suck_u2(cb);
- f->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
- f->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
-
+
+ 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;
+
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");
+ i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
- 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 ((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 ((f->flags & ACC_TRANSIENT) != 0)
- panic("Interface field declared transient");
+ 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 */
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 */
- if (!skipattributebody(cb))
- return false;
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
- } else {
- /* constant value attribute */
- if (pindex != field_load_NOVALUE)
- panic("Field has more than one ConstantValue attribute");
-
+ if (u == utf_constantvalue) {
if (!check_classbuffer_size(cb, 4 + 2))
return false;
/* 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;
}
}
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)
return false;
m->flags = suck_u2(cb);
- m->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
- m->descriptor = 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))
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 (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) != 0) {
+ if (m->flags & ACC_ABSTRACT) {
if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
*exceptionptr =
new_classformaterror(c,
- "Illegal method modifiers: 0x%x",
+ "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;
- aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
-
- if (aname != utf_code) {
- if (aname == utf_exceptions) {
- s4 j;
-
- 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++) {
- (m->thrownexceptions)[j] =
- class_getconstant(c, suck_u2(cb), CONSTANT_Class);
- }
-
- } else {
- if (!skipattributebody(cb))
- return false;
- }
+ if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
- } else {
+ if (aname == utf_code) {
if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
*exceptionptr =
new_classformaterror(c,
m->jcodelength = suck_u4(cb);
- if (m->jcodelength == 0)
- panic("bytecode has zero length");
+ if (m->jcodelength == 0) {
+ *exceptionptr =
+ new_classformaterror(c, "Code of a method has length 0");
+ return false;
+ }
+
if (m->jcodelength > 65535) {
*exceptionptr =
new_classformaterror(c,
return false;
m->exceptiontablelength = suck_u2(cb);
-
if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
return false;
m->exceptiontable[j].catchtype = NULL;
} else {
- m->exceptiontable[j].catchtype =
- class_getconstant(c, idx, CONSTANT_Class);
+ if (!(m->exceptiontable[j].catchtype =
+ class_getconstant(c, idx, CONSTANT_Class)))
+ return false;
}
}
if (!check_classbuffer_size(cb, 2))
return false;
- caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+ if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
if (caname == utf_linenumbertable) {
u2 lncid;
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;
}
}
}
/* everything was ok */
+ /* utf_display(m->name);
+ printf("\nexceptiontablelength:%ld\n",m->exceptiontablelength);*/
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,
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 */
if (!check_classbuffer_size(cb, 2))
return false;
- u4 cpcount = c->cpcount = suck_u2(cb);
+ 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;
+ }
#if defined(STATISTICS)
if (opt_stat)
idx = 1;
while (idx < cpcount) {
+ u4 t;
+
/* get constant type */
if (!check_classbuffer_size(cb, 1))
return false;
- u4 t = suck_u1(cb);
+ t = suck_u1(cb);
switch (t) {
- case CONSTANT_Class: {
- forward_class *nfc = DNEW(forward_class);
-
- 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;
+ case CONSTANT_Class:
+ nfc = NEW(forward_class);
- nff->thisindex = idx;
- /* constant type */
- nff->tag = t;
+ nfc->next = forward_classes;
+ forward_classes = nfc;
- if (!check_classbuffer_size(cb, 2 + 2))
+ nfc->thisindex = idx;
+ /* reference to CONSTANT_NameAndType */
+ if (!check_classbuffer_size(cb, 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);
+ nfc->name_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;
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;
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);
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;
}
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) */
if (!check_classbuffer_size(cb, 2))
return false;
- u4 length = suck_u2(cb);
+ length = suck_u2(cb);
cptags[idx] = CONSTANT_Utf8;
/* validate the string */
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_intern(cb->pos + 1, length);
+ cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
/* skip bytes of the string (buffer size check above) */
skip_nbytes(cb, length);
}
default:
- error("Unkown constant type: %d",(int) t);
+ *exceptionptr =
+ new_classformaterror(c, "Illegal constant pool type");
+ return false;
} /* end switch */
} /* end while */
if (!class_load(tc))
return false;
- /* link the class later, so we cannot link the currently loaded
- class */
+ /* link the class later, because we cannot link the class currently
+ loading */
list_addfirst(&unlinkedclasses, tc);
cpinfos[forward_classes->thisindex] = tc;
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) {
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) {
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;
}
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 (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
*exceptionptr =
- new_classformaterror(c,
- "Unsupported major.minor version %d.%d",
- ma, mi);
+ new_unsupportedclassversionerror(c,
+ "Unsupported major.minor version %d.%d",
+ ma, mi);
return NULL;
}
+ /* load the constant pool */
if (!class_loadcpool(cb, c))
return NULL;
if (c->flags & ACC_FINAL) {
*exceptionptr =
new_classformaterror(c,
- "Illegal class modifiers: 0x%x", c->flags);
+ "Illegal class modifiers: 0x%X", c->flags);
return NULL;
}
if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
*exceptionptr =
- new_classformaterror(c, "Illegal class modifiers: 0x%x", c->flags);
+ new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
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) {
return NULL;
}
-
}
/* retrieve interfaces */
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 */
}
/* 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;
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;
}
#endif
- /* load variable-length attribute structures */
+ /* load attribute structures */
if (!check_classbuffer_size(cb, 2))
return NULL;
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;
}
}
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_intern(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.");
case 'L':
/* c is an array of objects. */
-/* comp = class_get(utf_new_intern(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.");
/* 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 (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)
- if (!class_load(ic))
+ if (!tc->loaded)
+ if (!class_load(tc))
return NULL;
- if (!ic->linked)
- if (!class_link(ic))
- 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 (!class_load(super))
return NULL;
+ if (super->flags & ACC_INTERFACE) {
+ /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
+ panic("Interface specified as super class");
+ }
+
+ /* Don't allow extending final classes */
+ 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;
- if (super->flags & ACC_INTERFACE)
- 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");
- }
- }
+ if (c->name->text[0] == '[')
+ if (!(arraydesc = class_link_array(c)))
+ return NULL;
- /* Don't allow extending final classes */
- if (super->flags & ACC_FINAL)
- panic("Trying to extend final class");
-
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;
}
void class_free(classinfo *c)
{
s4 i;
- vftbl *v;
+ vftbl_t *v;
class_freecpool(c);
}
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);
}
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 */
/* prevent loader from loading primitive class */
c->loaded = true;
- class_link(c);
+ if (!class_link(c))
+ return false;
primitivetype_table[i].class_primitive = c;
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;
}
/* These classes have to be created now because the classinfo
* pointers are used in the loading code.
*/
- class_java_lang_Object =
- class_new_intern(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_intern(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_intern(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_intern(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;
}