/* src/vm/loader.c - class loader functions
- 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
+ Copyright (C) 1996-2005, 2006 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
+ Contact: cacao@cacaojvm.org
Authors: Reinhard Grafl
Edwin Steiner
Christian Thalinger
- $Id: loader.c 3903 2005-12-07 17:43:29Z twisti $
+ $Id: loader.c 5250 2006-08-18 12:24:10Z twisti $
*/
+
+#include "config.h"
+
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#include "config.h"
#include "vm/types.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
+#if defined(ENABLE_THREADS)
+# include "threads/native/threads.h"
#endif
#include "toolbox/logging.h"
-#include "vm/exceptions.h"
#include "vm/builtin.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/linker.h"
#include "vm/loader.h"
#include "vm/statistics.h"
#include "vm/stringlocal.h"
#include "vm/suck.h"
-#include "vm/classcache.h"
+#include "vm/vm.h"
-#if defined(USE_ZLIB)
-# include "vm/unzip.h"
+#if defined(ENABLE_ZLIB)
+# include "vm/zip.h"
#endif
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen.inc.h"
+#include "vm/jit/codegen-common.h"
+#include "vm/rt-timing.h"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
/******************************************************************************/
/* DEBUG HELPERS */
#endif
-/********************************************************************
- list of classpath entries (either filesystem directories or
- ZIP/JAR archives
-********************************************************************/
-
-classpath_info *classpath_entries = NULL;
-
-
/* loader_init *****************************************************************
Initializes all lists and loads all classes required for the system
*******************************************************************************/
-bool loader_init(u1 *stackbottom)
+bool loader_init(void)
{
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- classpath_info *cpi;
+#if defined(ENABLE_THREADS)
+ list_classpath_entry *lce;
/* Initialize the monitor pointer for zip/jar file locking. */
- for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
- if (cpi->type == CLASSPATH_ARCHIVE)
- initObjectLock(&cpi->header);
- }
+ for (lce = list_first(list_classpath_entries); lce != NULL;
+ lce = list_next(list_classpath_entries, lce))
+ if (lce->type == CLASSPATH_ARCHIVE)
+ lock_init_object_lock((java_objectheader *) lce);
#endif
/* load some important classes */
load_class_bootstrap(utf_java_lang_ThreadGroup)))
return false;
+ if (!(class_java_lang_VMSystem =
+ load_class_bootstrap(utf_new_char("java/lang/VMSystem"))))
+ return false;
+
if (!(class_java_lang_VMThread =
load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
return false;
load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
return false;
-#if defined(USE_THREADS)
- if (stackbottom != 0)
- initLocks();
-#endif
-
return true;
}
void loader_load_all_classes(void)
{
- classpath_info *cpi;
- classinfo *c;
+ list_classpath_entry *lce;
+#if defined(ENABLE_ZLIB)
+ hashtable *ht;
+ s4 slot;
+ hashtable_zipfile_entry *htzfe;
+ utf *u;
+#endif
- for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
-#if defined(USE_ZLIB)
- if (cpi->type == CLASSPATH_ARCHIVE) {
- cacao_entry_s *ce;
- unz_s *s;
+ for (lce = list_first(list_classpath_entries); lce != NULL;
+ lce = list_next(list_classpath_entries, lce)) {
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+ /* get the classes hashtable */
- s = (unz_s *) cpi->uf;
- ce = s->cacao_dir_list;
-
- while (ce) {
- /* skip all entries in META-INF and .properties, .png files */
+ ht = lce->htclasses;
- if (strncmp(ce->name->text, "META-INF", strlen("META-INF")) &&
- !strstr(ce->name->text, ".properties") &&
- !strstr(ce->name->text, ".png"))
- c = load_class_bootstrap(ce->name);
+ for (slot = 0; slot < ht->size; slot++) {
+ htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
- ce = ce->next;
- }
+ for (; htzfe; htzfe = htzfe->hashlink) {
+ u = htzfe->filename;
- } else {
-#endif
-#if defined(USE_ZLIB)
- }
-#endif
- }
-}
+ /* skip all entries in META-INF and .properties,
+ .png files */
+ if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
+ strstr(u->text, ".properties") ||
+ strstr(u->text, ".png"))
+ continue;
-/******************************************************************************/
-/******************* Some support functions ***********************************/
-/******************************************************************************/
+ /* load class from bootstrap classloader */
-void fprintflags (FILE *fp, u2 f)
-{
- if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
- if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
- if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
- if ( f & ACC_STATIC ) fprintf (fp," STATIC");
- if ( f & ACC_FINAL ) fprintf (fp," FINAL");
- if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
- if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
- if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
- if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
- if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
- if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
-}
+ if (!load_class_bootstrap(u)) {
+ fprintf(stderr, "Error loading: ");
+ utf_fprint_printable_ascii_classname(stderr, u);
+ fprintf(stderr, "\n");
+#if !defined(NDEBUG)
+ /* print out exception and cause */
-/********** internal function: printflags (only for debugging) ***************/
+ exceptions_print_exception(*exceptionptr);
+#endif
+ }
+ }
+ }
-void printflags(u2 f)
-{
- fprintflags(stdout,f);
+ } else {
+#endif
+#if defined(ENABLE_ZLIB)
+ }
+#endif
+ }
}
-/********************** Function: skipattributebody ****************************
+/* skipattributebody ***********************************************************
- skips an attribute after the 16 bit reference to attribute_name has already
- been read
+ Skips an attribute after the 16 bit reference to attribute_name has
+ already been read.
*******************************************************************************/
cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
if (cpcount < 1) {
- *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
+ exceptions_throw_classformaterror(c, "Illegal constant pool size");
return false;
}
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
#endif
case CONSTANT_Integer: {
constant_integer *ci = NEW(constant_integer);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_const_pool_len += sizeof(constant_integer);
#endif
case CONSTANT_Float: {
constant_float *cf = NEW(constant_float);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_const_pool_len += sizeof(constant_float);
#endif
case CONSTANT_Long: {
constant_long *cl = NEW(constant_long);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_const_pool_len += sizeof(constant_long);
#endif
cpinfos[idx] = cl;
idx += 2;
if (idx > cpcount) {
- *exceptionptr =
- new_classformaterror(c, "Invalid constant pool entry");
+ exceptions_throw_classformaterror(c, "Invalid constant pool entry");
return false;
}
break;
case CONSTANT_Double: {
constant_double *cd = NEW(constant_double);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_const_pool_len += sizeof(constant_double);
#endif
cpinfos[idx] = cd;
idx += 2;
if (idx > cpcount) {
- *exceptionptr =
- new_classformaterror(c, "Invalid constant pool entry");
+ exceptions_throw_classformaterror(c, "Invalid constant pool entry");
return false;
}
break;
if (opt_verify &&
!is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
{
- *exceptionptr = new_classformaterror(c,"Invalid UTF-8 string");
+ exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
return false;
}
#endif /* ENABLE_VERIFIER */
}
default:
- *exceptionptr =
- new_classformaterror(c, "Illegal constant pool type");
+ exceptions_throw_classformaterror(c, "Illegal constant pool type");
return false;
} /* end switch */
} /* end while */
#ifdef ENABLE_VERIFIER
if (opt_verify && !is_valid_name_utf(name)) {
- *exceptionptr =
- new_classformaterror(c, "Class reference with invalid name");
+ exceptions_throw_classformaterror(c, "Class reference with invalid name");
return false;
}
#endif /* ENABLE_VERIFIER */
/* link the class later, because we cannot link the class currently
loading */
- list_addfirst(&unlinkedclasses, tc);
+ list_add_first(&unlinkedclasses, tc);
}
/* the classref is created later */
while (forward_nameandtypes) {
constant_nameandtype *cn = NEW(constant_nameandtype);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_const_pool_len += sizeof(constant_nameandtype);
#endif
if (opt_verify) {
/* check name */
if (!is_valid_name_utf(cn->name)) {
- *exceptionptr =
- new_classformaterror(c,
- "Illegal Field name \"%s\"",
- cn->name->text);
+ exceptions_throw_classformaterror(c,
+ "Illegal Field name \"%s\"",
+ cn->name->text);
return false;
}
/* disallow referencing <clinit> among others */
if (cn->name->text[0] == '<' && cn->name != utf_init) {
- *exceptionptr =
- new_classformaterror(c,"Illegal reference to special method");
+ exceptions_throw_classformaterror(c, "Illegal reference to special method");
return false;
}
}
constant_nameandtype *nat;
constant_FMIref *fmi = NEW(constant_FMIref);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_const_pool_len += sizeof(constant_FMIref);
#endif
/* the classref is created later */
- fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
+ fmi->p.index = forward_fieldmethints->class_index;
fmi->name = nat->name;
fmi->descriptor = nat->descriptor;
/* descriptor_pool_add accepts method descriptors, so we have to check */
/* against them here before the call of descriptor_to_basic_type below. */
if (u->text[0] == '(') {
- *exceptionptr = new_classformaterror(c,"Method descriptor used for field");
+ exceptions_throw_classformaterror(c, "Method descriptor used for field");
return false;
}
if (opt_verify) {
/* check name */
if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
- *exceptionptr = new_classformaterror(c,
- "Illegal Field name \"%s\"",
- f->name->text);
+ exceptions_throw_classformaterror(c,
+ "Illegal Field name \"%s\"",
+ f->name->text);
return false;
}
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);
+ exceptions_throw_classformaterror(c,
+ "Illegal field modifiers: 0x%X",
+ f->flags);
return false;
}
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);
+ exceptions_throw_classformaterror(c,
+ "Illegal field modifiers: 0x%X",
+ f->flags);
return false;
}
}
}
#endif /* ENABLE_VERIFIER */
-
- f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
- f->offset = 0; /* offset from start of object */
- f->class = c;
- f->xta = NULL;
-
+
+ f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
+ f->offset = 0; /* offset from start of object */
+ f->class = c;
+
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_LONG:
+ case TYPE_INT:
+ f->value.i = 0;
+ break;
+
+ case TYPE_FLT:
+ f->value.f = 0.0;
+ break;
+
+ case TYPE_DBL:
+ f->value.d = 0.0;
+ break;
+
+ case TYPE_ADR:
+ f->value.a = NULL;
+ if (!(f->flags & ACC_STATIC))
+ c->flags |= ACC_CLASS_HAS_POINTERS;
+ break;
+
+ case TYPE_LNG:
#if U8_AVAILABLE
- f->value.l = 0; break;
+ f->value.l = 0;
#else
- f->value.l.low = 0; f->value.l.high = 0; break;
+ f->value.l.low = 0;
+ f->value.l.high = 0;
#endif
+ break;
}
/* read attributes */
/* check attribute length */
if (suck_u4(cb) != 2) {
- *exceptionptr =
- new_classformaterror(c, "Wrong size for VALUE attribute");
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
return false;
}
/* constant value attribute */
if (pindex != field_load_NOVALUE) {
- *exceptionptr =
- new_classformaterror(c,
- "Multiple ConstantValue attributes");
+ exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
return false;
}
}
break;
- case TYPE_LONG: {
+ case TYPE_LNG: {
constant_long *cl;
if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
}
break;
- case TYPE_FLOAT: {
+ case TYPE_FLT: {
constant_float *cf;
if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
}
break;
- case TYPE_DOUBLE: {
+ case TYPE_DBL: {
constant_double *cd;
if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
}
break;
- case TYPE_ADDRESS:
+ case TYPE_ADR:
if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
return false;
c = cb->class;
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- initObjectLock(&m->header);
+#if defined(ENABLE_THREADS)
+ lock_init_object_lock(&m->header);
#endif
-#ifdef STATISTICS
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_all_methods++;
#endif
- m->thrownexceptionscount = 0;
- m->linenumbercount = 0;
- m->linenumbers = 0;
- m->class = c;
- m->nativelyoverloaded = false;
+ /* all fields of m have been zeroed in load_class_from_classbuffer */
+
+ m->class = c;
if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
return false;
return false;
m->descriptor = u;
- m->parseddesc = NULL;
if (!descriptor_pool_add(descpool, u, &argcount))
return false;
#ifdef ENABLE_VERIFIER
if (opt_verify) {
if (!is_valid_name_utf(m->name)) {
- *exceptionptr = new_classformaterror(c,"Method with invalid name");
+ exceptions_throw_classformaterror(c, "Method with invalid name");
return false;
}
if (m->name->text[0] == '<' &&
m->name != utf_init && m->name != utf_clinit) {
- *exceptionptr = new_classformaterror(c,"Method with invalid special name");
+ exceptions_throw_classformaterror(c, "Method with invalid special name");
return false;
}
}
#ifdef ENABLE_VERIFIER
if (opt_verify) {
if (argcount > 255) {
- *exceptionptr =
- new_classformaterror(c, "Too many arguments in signature");
+ exceptions_throw_classformaterror(c, "Too many arguments in signature");
return false;
}
i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
- *exceptionptr =
- new_classformaterror(c,
- "Illegal method modifiers: 0x%X",
- m->flags);
+ exceptions_throw_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))) {
- *exceptionptr =
- new_classformaterror(c,
- "Illegal method modifiers: 0x%X",
- m->flags);
+ exceptions_throw_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
return false;
}
}
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);
+ exceptions_throw_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)) {
- *exceptionptr = new_classformaterror(c,
- "Instance initialization method has invalid flags set");
+ exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
return false;
}
}
}
#endif /* ENABLE_VERIFIER */
- 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->stubroutine = NULL;
- m->mcode = NULL;
- m->entrypoint = NULL;
- m->methodUsed = NOTUSED;
- m->monoPoly = MONO;
- m->subRedefs = 0;
- m->subRedefsUsed = 0;
-
- m->xta = NULL;
-
if (!suck_check_classbuffer_size(cb, 2))
return false;
if (aname == utf_Code) {
if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
- *exceptionptr =
- new_classformaterror(c,
- "Code attribute in native or abstract methods");
-
- return false;
+ exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
+ return false;
}
if (m->jcode) {
- *exceptionptr =
- new_classformaterror(c, "Multiple Code attributes");
-
+ exceptions_throw_classformaterror(c, "Multiple Code attributes");
return false;
}
m->maxlocals = suck_u2(cb);
if (m->maxlocals < argcount) {
- *exceptionptr =
- new_classformaterror(c, "Arguments can't fit into locals");
-
+ exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
return false;
}
m->jcodelength = suck_u4(cb);
if (m->jcodelength == 0) {
- *exceptionptr =
- new_classformaterror(c, "Code of a method has length 0");
-
+ exceptions_throw_classformaterror(c, "Code of a method has length 0");
return false;
}
if (m->jcodelength > 65535) {
- *exceptionptr =
- new_classformaterror(c,
- "Code of a method longer than 65535 bytes");
-
+ exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
return false;
}
m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat) {
count_vmcode_len += m->jcodelength + 18;
count_extable_len +=
s4 j;
if (m->thrownexceptions) {
- *exceptionptr =
- new_classformaterror(c, "Multiple Exceptions attributes");
+ exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
return false;
}
}
if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
- *exceptionptr = new_classformaterror(c, "Missing Code attribute");
-
+ exceptions_throw_classformaterror(c, "Missing Code attribute");
return false;
}
if (aname == utf_InnerClasses) {
/* innerclasses attribute */
if (c->innerclass) {
- *exceptionptr =
- new_classformaterror(c, "Multiple InnerClasses attributes");
+ exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
return false;
}
return false;
if (suck_u4(cb) != 2) {
- *exceptionptr =
- new_classformaterror(c, "Wrong size for VALUE attribute");
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
return false;
}
if (c->sourcefile) {
- *exceptionptr =
- new_classformaterror(c, "Multiple SourceFile attributes");
+ exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
return false;
}
if (!m)
return false;
- cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
+ cl = vm_call_method(m, NULL);
if (!cl)
return false;
classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
{
- classinfo *c;
- classinfo *tmpc;
+ java_objectheader *o;
+ classinfo *c;
+ classinfo *tmpc;
+ java_lang_String *s;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_lookup, time_prepare, time_java,
+ time_cache;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
LOADER_ASSERT(name);
c = classcache_lookup(cl, name);
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
+
if (c)
return c;
if (!lc)
return false; /* exception */
- c = (classinfo *) asm_calljavafunction(lc,
- cl,
- javastring_new_slash_to_dot(name),
- NULL, NULL);
+ /* move return value into `o' and cast it afterwards to a classinfo* */
+
+ s = javastring_new_slash_to_dot(name);
+
+ RT_TIMING_GET_TIME(time_prepare);
+
+ o = vm_call_method(lc, cl, s);
+
+ RT_TIMING_GET_TIME(time_java);
+
+ c = (classinfo *) o;
if (c) {
/* Store this class in the loaded class cache. If another
c = tmpc;
} else {
- /* loadClass has thrown an exception */
- /* we must convert ClassNotFoundException into NoClassDefFoundException */
- /* XXX maybe we should have a flag that avoids this conversion */
- /* for calling load_class_from_classloader from Class.forName */
- /* Currently we do a double conversion in these cases */
+ /* loadClass has thrown an exception. We must convert
+ ClassNotFoundException into
+ NoClassDefFoundException. */
+
+ /* XXX Maybe we should have a flag that avoids this
+ conversion for calling load_class_from_classloader from
+ Class.forName. Currently we do a double conversion in
+ these cases. */
+
classnotfoundexception_to_noclassdeffounderror();
}
+ RT_TIMING_GET_TIME(time_cache);
+
+ RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
+ RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
+ RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
+
/* SUN compatible -verbose:class output */
if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
printf("[Loaded ");
- utf_display_classname(name);
+ utf_display_printable_ascii_classname(name);
printf("]\n");
}
+#if defined(ENABLE_JVMTI)
+ /* fire Class Load JVMTI event */
+ if (jvmti) jvmti_ClassLoadPrepare(false, c);
+#endif
+
+
return c;
}
classbuffer *cb;
classinfo *c;
classinfo *r;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_lookup, time_array, time_suck,
+ time_load, time_cache;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
/* for debugging */
/* lookup if this class has already been loaded */
- if ((r = classcache_lookup(NULL, name)))
+ if ((r = classcache_lookup(NULL, name))) {
+
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
+
return r;
+ }
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
+
/* create the classinfo */
c = class_create_classinfo(name);
-
+
/* handle array classes */
if (name->text[0] == '[') {
if (c == NULL)
return NULL;
LOADER_ASSERT(c->state & CLASS_LOADED);
+
+ RT_TIMING_GET_TIME(time_array);
+ RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
+
return c;
}
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
/* measure time */
- if (getcompilingtime)
+ if (opt_getcompilingtime)
compilingtime_stop();
- if (getloadingtime)
+ if (opt_getloadingtime)
loadingtime_start();
#endif
return NULL;
}
+
+ RT_TIMING_GET_TIME(time_suck);
/* load the class from the buffer */
r = load_class_from_classbuffer(cb);
+ RT_TIMING_GET_TIME(time_load);
+
if (!r) {
/* the class could not be loaded, free the classinfo struct */
r = res;
}
+ RT_TIMING_GET_TIME(time_cache);
+
/* SUN compatible -verbose:class output */
if (opt_verboseclass && r) {
printf("[Loaded ");
- utf_display_classname(name);
+ utf_display_printable_ascii_classname(name);
printf(" from %s]\n", cb->path);
}
suck_stop(cb);
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
/* measure time */
- if (getloadingtime)
+ if (opt_getloadingtime)
loadingtime_stop();
- if (getcompilingtime)
+ if (opt_getcompilingtime)
compilingtime_start();
#endif
+ RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
+ RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
+ RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
+ RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
+
return r;
}
u4 ma, mi;
s4 dumpsize;
descriptor_pool *descpool;
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
u4 classrefsize;
u4 descsize;
#endif
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_checks, time_ndpool, time_cpool,
+ time_setup, time_fields, time_methods, time_classrefs,
+ time_descs, time_setrefs, time_parsefds, time_parsemds,
+ time_parsecpool, time_verify, time_attrs;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
/* get the classbuffer's class */
if (c->state & CLASS_LOADED)
return c;
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat)
count_class_loads++;
#endif
+#if !defined(NDEBUG)
/* output for debugging purposes */
if (loadverbose)
log_message_class("Loading class: ", c);
-
+#endif
+
/* mark start of dump memory area */
dumpsize = dump_size();
/* check signature */
if (suck_u4(cb) != MAGIC) {
- *exceptionptr = new_classformaterror(c, "Bad magic number");
+ exceptions_throw_classformaterror(c, "Bad magic number");
goto return_exception;
}
goto return_exception;
}
+ RT_TIMING_GET_TIME(time_checks);
/* create a new descriptor pool */
descpool = descriptor_pool_new(c);
+ RT_TIMING_GET_TIME(time_ndpool);
+
/* load the constant pool */
if (!load_constantpool(cb, descpool))
goto return_exception;
- c->classUsed = NOTUSED; /* not used initially CO-RT */
- c->impldBy = NULL;
+ RT_TIMING_GET_TIME(time_cpool);
/* ACC flags */
}
if (c->flags & ACC_FINAL) {
- *exceptionptr =
- new_classformaterror(c,
- "Illegal class modifiers: 0x%X", c->flags);
-
+ exceptions_throw_classformaterror(c,
+ "Illegal class modifiers: 0x%X",
+ c->flags);
goto return_exception;
}
}
if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
- *exceptionptr =
- new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
-
+ exceptions_throw_classformaterror(c,
+ "Illegal class modifiers: 0x%X",
+ c->flags);
goto return_exception;
}
char *msg;
s4 msglen;
- msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
- utf_strlen(name) + strlen(")") + strlen("0");
+ msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
+ utf_bytes(name) + strlen(")") + strlen("0");
msg = MNEW(char, msglen);
- utf_sprint(msg, c->name);
+ utf_copy_classname(msg, c->name);
strcat(msg, " (wrong name: ");
- utf_strcat(msg, name);
+ utf_cat_classname(msg, name);
strcat(msg, ")");
*exceptionptr =
goto return_exception;
}
-
+
/* retrieve superclass */
c->super.any = NULL;
/* This is only allowed for java.lang.Object. */
if (c->name != utf_java_lang_Object) {
- *exceptionptr = new_classformaterror(c, "Bad superclass index");
-
+ exceptions_throw_classformaterror(c, "Bad superclass index");
goto return_exception;
}
}
-
+
/* retrieve interfaces */
if (!suck_check_classbuffer_size(cb, 2))
goto return_exception;
}
+ RT_TIMING_GET_TIME(time_setup);
+
/* load fields */
if (!suck_check_classbuffer_size(cb, 2))
goto return_exception;
goto return_exception;
}
+ RT_TIMING_GET_TIME(time_fields);
+
/* load methods */
if (!suck_check_classbuffer_size(cb, 2))
goto return_exception;
c->methodscount = suck_u2(cb);
/* c->methods = GCNEW(methodinfo, c->methodscount); */
c->methods = MNEW(methodinfo, c->methodscount);
+
+ MZERO(c->methods, methodinfo, c->methodscount);
+
for (i = 0; i < c->methodscount; i++) {
if (!load_method(cb, &(c->methods[i]),descpool))
goto return_exception;
}
+ RT_TIMING_GET_TIME(time_methods);
+
/* create the class reference table */
c->classrefs =
descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
+ RT_TIMING_GET_TIME(time_classrefs);
+
/* allocate space for the parsed descriptors */
descriptor_pool_alloc_parsed_descriptors(descpool);
c->parseddescs =
descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
if (opt_stat) {
descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
count_classref_len += classrefsize;
}
#endif
+ RT_TIMING_GET_TIME(time_descs);
+
/* put the classrefs in the constant pool */
for (i = 0; i < c->cpcount; i++) {
if (c->cptags[i] == CONSTANT_Class) {
goto return_exception;
}
+ RT_TIMING_GET_TIME(time_setrefs);
+
/* parse field descriptors */
for (i = 0; i < c->fieldscount; i++) {
goto return_exception;
}
+ RT_TIMING_GET_TIME(time_parsefds);
+
/* parse method descriptors */
for (i = 0; i < c->methodscount; i++) {
}
}
+ RT_TIMING_GET_TIME(time_parsemds);
+
/* parse the loaded descriptors */
for (i = 0; i < c->cpcount; i++) {
constant_FMIref *fmi;
s4 index;
-
+
switch (c->cptags[i]) {
case CONSTANT_Fieldref:
fmi = (constant_FMIref *) c->cpinfos[i];
fmi->descriptor);
if (!fmi->parseddesc.fd)
goto return_exception;
- index = (int) (size_t) fmi->classref;
- fmi->classref =
+ index = fmi->p.index;
+ fmi->p.classref =
(constant_classref *) class_getconstant(c, index,
CONSTANT_Class);
- if (!fmi->classref)
+ if (!fmi->p.classref)
goto return_exception;
break;
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
fmi = (constant_FMIref *) c->cpinfos[i];
- index = (int) (size_t) fmi->classref;
- fmi->classref =
+ index = fmi->p.index;
+ fmi->p.classref =
(constant_classref *) class_getconstant(c, index,
CONSTANT_Class);
- if (!fmi->classref)
+ if (!fmi->p.classref)
goto return_exception;
fmi->parseddesc.md =
descriptor_pool_parse_method_descriptor(descpool,
fmi->descriptor,
ACC_UNDEF,
- fmi->classref);
+ fmi->p.classref);
if (!fmi->parseddesc.md)
goto return_exception;
break;
}
}
+ RT_TIMING_GET_TIME(time_parsecpool);
+
#ifdef ENABLE_VERIFIER
/* Check if all fields and methods can be uniquely
* identified by (name,descriptor). */
do {
if (c->fields[old].name == fi->name &&
c->fields[old].descriptor == fi->descriptor) {
- *exceptionptr =
- new_classformaterror(c,
- "Repetitive field name/signature");
-
+ exceptions_throw_classformaterror(c, "Repetitive field name/signature");
goto return_exception;
}
} while ((old = next[old]));
}
hashtab[index] = i + 1;
}
-
+
/* Check methods */
memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
do {
if (c->methods[old].name == mi->name &&
c->methods[old].descriptor == mi->descriptor) {
- *exceptionptr =
- new_classformaterror(c,
- "Repetitive method name/signature");
-
+ exceptions_throw_classformaterror(c, "Repetitive method name/signature");
goto return_exception;
}
} while ((old = next[old]));
}
hashtab[index] = i + 1;
}
-
+
MFREE(hashtab, u2, (hashlen + len));
}
#endif /* ENABLE_VERIFIER */
-#if defined(STATISTICS)
+ RT_TIMING_GET_TIME(time_verify);
+
+#if defined(ENABLE_STATISTICS)
if (opt_stat) {
- count_class_infos += sizeof(classinfo*) * c->interfacescount;
- count_class_infos += sizeof(fieldinfo) * c->fieldscount;
- count_class_infos += sizeof(methodinfo) * c->methodscount;
+ size_classinfo += sizeof(classinfo*) * c->interfacescount;
+ size_fieldinfo += sizeof(fieldinfo) * c->fieldscount;
+ size_methodinfo += sizeof(methodinfo) * c->methodscount;
}
#endif
if (!load_attributes(cb, suck_u2(cb)))
goto return_exception;
-#if 0
- /* 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
+ /* 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) {
+
+ if (((ma == 45) && (mi > 3)) || (ma > 45)) {
/* check if all data has been read */
s4 classdata_left = ((cb->data + cb->size) - cb->pos);
if (classdata_left > 0) {
- *exceptionptr =
- new_classformaterror(c, "Extra bytes at the end of class file");
+ exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
goto return_exception;
}
}
-#endif
+
+ RT_TIMING_GET_TIME(time_attrs);
/* release dump area */
c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
+#if defined(ENABLE_JVMTI)
+ /* fire Class Prepare JVMTI event */
+
+ if (jvmti)
+ jvmti_ClassLoadPrepare(true, c);
+#endif
+
+#if !defined(NDEBUG)
if (loadverbose)
log_message_class("Loading done class: ", c);
+#endif
+
+ RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
+ RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
+ RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
+ RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
+ RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
+ RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
+ RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
+ RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
+ RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
+ RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
+ RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
+ RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
+ RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
+ RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
+ RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
return c;
tc = class_java_lang_Cloneable;
LOADER_ASSERT(tc->state & CLASS_LOADED);
- list_addfirst(&unlinkedclasses, tc);
+ list_add_first(&unlinkedclasses, tc);
c->interfaces[0].cls = tc;
tc = class_java_io_Serializable;
LOADER_ASSERT(tc->state & CLASS_LOADED);
- list_addfirst(&unlinkedclasses, tc);
+ list_add_first(&unlinkedclasses, tc);
c->interfaces[1].cls = tc;
} else {
/* create descriptor for clone method */
/* we need one paramslot which is reserved for the 'this' parameter */
clonedesc = NEW(methoddesc);
- clonedesc->returntype.type = TYPE_ADDRESS;
+ clonedesc->returntype.type = TYPE_ADR;
clonedesc->returntype.classref = classrefs + 1;
clonedesc->returntype.arraydim = 0;
/* initialize params to "empty", add real params below in
clonedesc->paramcount = 0;
clonedesc->paramslots = 0;
clonedesc->paramtypes[0].classref = classrefs + 0;
+ clonedesc->params = NULL;
/* create methodinfo */
clone = c->methods;
MSET(clone, 0, methodinfo, 1);
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- initObjectLock(&clone->header);
+#if defined(ENABLE_THREADS)
+ lock_init_object_lock(&clone->header);
#endif
- /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter
- related) */
- clone->flags = ACC_PUBLIC | ACC_NATIVE;
- clone->name = utf_clone;
+ /* ATTENTION: if you delete the ACC_NATIVE below, set
+ clone->maxlocals=1 (interpreter related) */
+
+ clone->flags = ACC_PUBLIC | ACC_NATIVE;
+ clone->name = utf_clone;
clone->descriptor = utf_void__java_lang_Object;
clone->parseddesc = clonedesc;
- clone->class = c;
- clone->monoPoly = MONO;
+ clone->class = c;
/* parse the descriptor to get the register allocation */
if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
return false;
- clone->entrypoint =
+ clone->code =
codegen_createnativestub((functionptr) &builtin_clone_array, clone);
/* XXX: field: length? */
/* array classes are not loaded from class files */
- c->state |= CLASS_LOADED;
- c->parseddescs = (u1 *) clonedesc;
+ c->state |= CLASS_LOADED;
+ c->parseddescs = (u1 *) clonedesc;
c->parseddescsize = sizeof(methodinfo);
- c->classrefs = classrefs;
- c->classrefcount = 1;
+ c->classrefs = classrefs;
+ c->classrefcount = 1;
/* insert class into the loaded class cache */
/* XXX free classinfo if NULL returned? */
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/