* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / loader.c
index c0a8aafb4e0dd26d0d724c662efed454424a10d2..2abe53ed3326c29dc86f058e7008e507b1c5d3d6 100644 (file)
@@ -1,9 +1,9 @@
 /* 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 3813 2005-11-28 18:31:29Z edwin $
+   $Id: loader.c 4357 2006-01-22 23:33:38Z twisti $
 
 */
 
+
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-#include <sys/stat.h>
 
-#include "config.h"
 #include "vm/types.h"
+
 #include "mm/memory.h"
 #include "native/native.h"
 #include "native/include/java_lang_Throwable.h"
 #endif
 
 #include "toolbox/logging.h"
-#include "toolbox/util.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/options.h"
 #include "vm/statistics.h"
 #include "vm/stringlocal.h"
-#include "vm/tables.h"
-#include "vm/classcache.h"
+#include "vm/suck.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"
+
 
 /******************************************************************************/
 /* 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
@@ -109,14 +103,14 @@ classpath_info *classpath_entries = NULL;
 bool loader_init(u1 *stackbottom)
 {
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       classpath_info *cpi;
+       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)
+                       initObjectLock((java_objectheader *) lce);
 #endif
 
        /* load some important classes */
@@ -236,303 +230,6 @@ bool loader_init(u1 *stackbottom)
 }
 
 
-/************* functions for reading classdata *********************************
-
-    getting classdata in blocks of variable size
-    (8,16,32,64-bit integer or float)
-
-*******************************************************************************/
-
-/* check_classbuffer_size ******************************************************
-
-   assert that at least <len> bytes are left to read
-   <len> is limited to the range of non-negative s4 values
-
-*******************************************************************************/
-
-inline bool check_classbuffer_size(classbuffer *cb, s4 len)
-{
-#ifdef ENABLE_VERIFIER
-       if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
-               *exceptionptr =
-                       new_classformaterror((cb)->class, "Truncated class file");
-
-               return false;
-       }
-#endif /* ENABLE_VERIFIER */
-
-       return true;
-}
-
-
-/* suck_nbytes *****************************************************************
-
-   transfer block of classfile data into a buffer
-
-*******************************************************************************/
-
-inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
-{
-       memcpy(buffer, cb->pos + 1, len);
-       cb->pos += len;
-}
-
-
-/* skip_nbytes ****************************************************************
-
-   skip block of classfile data
-
-*******************************************************************************/
-
-inline void skip_nbytes(classbuffer *cb, s4 len)
-{
-       cb->pos += len;
-}
-
-
-inline u1 suck_u1(classbuffer *cb)
-{
-       return *++(cb->pos);
-}
-
-
-inline u2 suck_u2(classbuffer *cb)
-{
-       u1 a = suck_u1(cb);
-       u1 b = suck_u1(cb);
-       return ((u2) a << 8) + (u2) b;
-}
-
-
-inline u4 suck_u4(classbuffer *cb)
-{
-       u1 a = suck_u1(cb);
-       u1 b = suck_u1(cb);
-       u1 c = suck_u1(cb);
-       u1 d = suck_u1(cb);
-       return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
-}
-
-
-/* get u8 from classfile data */
-static u8 suck_u8(classbuffer *cb)
-{
-#if U8_AVAILABLE
-       u8 lo, hi;
-       hi = suck_u4(cb);
-       lo = suck_u4(cb);
-       return (hi << 32) + lo;
-#else
-       u8 v;
-       v.high = suck_u4(cb);
-       v.low = suck_u4(cb);
-       return v;
-#endif
-}
-
-
-/* get float from classfile data */
-static float suck_float(classbuffer *cb)
-{
-       float f;
-
-#if !WORDS_BIGENDIAN 
-       u1 buffer[4];
-       u2 i;
-
-       for (i = 0; i < 4; i++)
-               buffer[3 - i] = suck_u1(cb);
-
-       memcpy((u1*) (&f), buffer, 4);
-#else
-       suck_nbytes((u1*) (&f), cb, 4);
-#endif
-
-       if (sizeof(float) != 4) {
-               *exceptionptr = new_internalerror("Incompatible float-format");
-
-               /* XXX should we exit in such a case? */
-               throw_exception_exit();
-       }
-       
-       return f;
-}
-
-
-/* get double from classfile data */
-static double suck_double(classbuffer *cb)
-{
-       double d;
-
-#if !WORDS_BIGENDIAN 
-       u1 buffer[8];
-       u2 i;   
-
-#if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
-       /*
-        * On little endian ARM processors when using FPA, word order
-        * of doubles is still big endian. So take that into account
-        * here. When using VFP, word order of doubles follows byte
-        * order. (michi 2005/07/24)
-        */
-       for (i = 0; i < 4; i++)
-               buffer[3 - i] = suck_u1(cb);
-       for (i = 0; i < 4; i++)
-               buffer[7 - i] = suck_u1(cb);
-#else
-       for (i = 0; i < 8; i++)
-               buffer[7 - i] = suck_u1(cb);
-#endif /* defined(__ARM__) && ... */
-
-       memcpy((u1*) (&d), buffer, 8);
-#else 
-       suck_nbytes((u1*) (&d), cb, 8);
-#endif
-
-       if (sizeof(double) != 8) {
-               *exceptionptr = new_internalerror("Incompatible double-format");
-
-               /* XXX should we exit in such a case? */
-               throw_exception_exit();
-       }
-       
-       return d;
-}
-
-
-/************************** function suck_init *********************************
-
-       called once at startup, sets the searchpath for the classfiles
-
-*******************************************************************************/
-
-void suck_init(char *classpath)
-{
-       char           *start;
-       char           *end;
-       char           *filename;
-       s4              filenamelen;
-       bool            is_zip;
-       classpath_info *cpi;
-       classpath_info *lastcpi;
-       char           *cwd;
-       s4              cwdlen;
-
-       /* search for last classpath entry (only if there already some) */
-
-       if ((lastcpi = classpath_entries)) {
-               while (lastcpi->next)
-                       lastcpi = lastcpi->next;
-       }
-
-       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) {
-                       is_zip = false;
-                       filenamelen = end - start;
-
-                       if (filenamelen > 3) {
-                               if (strncasecmp(end - 3, "zip", 3) == 0 ||
-                                       strncasecmp(end - 3, "jar", 3) == 0) {
-                                       is_zip = true;
-                               }
-                       }
-
-                       /* save classpath entries as absolute pathnames */
-
-                       cwd = NULL;
-                       cwdlen = 0;
-
-                       if (*start != '/') {                      /* XXX fix me for win32 */
-                               cwd = _Jv_getcwd();
-                               cwdlen = strlen(cwd) + strlen("/");
-                       }
-
-                       /* allocate memory for filename and fill it */
-
-                       filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
-                                                       strlen("0"));
-
-                       if (cwd) {
-                               strcpy(filename, cwd);
-                               strcat(filename, "/");
-                               strncat(filename, start, filenamelen);
-
-                               /* add cwd length to file length */
-                               filenamelen += cwdlen;
-
-                       } else {
-                               strncpy(filename, start, filenamelen);
-                               filename[filenamelen] = '\0';
-                       }
-
-                       cpi = NULL;
-
-                       if (is_zip) {
-#if defined(USE_ZLIB)
-                               unzFile uf = unzOpen(filename);
-
-                               if (uf) {
-                                       cpi = NEW(classpath_info);
-                                       cpi->type = CLASSPATH_ARCHIVE;
-                                       cpi->uf = uf;
-                                       cpi->next = NULL;
-                                       cpi->path = filename;
-                                       cpi->pathlen = filenamelen;
-
-                                       /* SUN compatible -verbose:class output */
-
-                                       if (opt_verboseclass)
-                                               printf("[Opened %s]\n", filename);
-                               }
-
-#else
-                               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                                  "zip/jar files not supported");
-#endif
-                               
-                       } else {
-                               cpi = NEW(classpath_info);
-                               cpi->type = CLASSPATH_PATH;
-                               cpi->next = NULL;
-
-                               if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
-                                       filename[filenamelen] = '/';
-                                       filename[filenamelen + 1] = '\0';
-                                       filenamelen++;
-                               }
-
-                               cpi->path = filename;
-                               cpi->pathlen = filenamelen;
-                       }
-
-                       /* attach current classpath entry */
-
-                       if (cpi) {
-                               if (!classpath_entries)
-                                       classpath_entries = cpi;
-                               else
-                                       lastcpi->next = cpi;
-
-                               lastcpi = cpi;
-                       }
-               }
-
-               /* goto next classpath entry, skip ':' delimiter */
-
-               if ((*end) == ':') {
-                       start = end + 1;
-
-               } else {
-                       start = end;
-               }
-       }
-}
-
-
 /* loader_load_all_classes *****************************************************
 
    Loads all classes specified in the BOOTCLASSPATH.
@@ -541,226 +238,61 @@ void suck_init(char *classpath)
 
 void loader_load_all_classes(void)
 {
-       classpath_info *cpi;
-       classinfo      *c;
-
-       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;
-
-                       s = (unz_s *) cpi->uf;
-                       ce = s->cacao_dir_list;
-                               
-                       while (ce) {
-                               /* skip all entries in META-INF and .properties, .png files */
-
-                               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);
-
-                               ce = ce->next;
-                       }
-
-               } else {
-#endif
-#if defined(USE_ZLIB)
-               }
-#endif
-       }
-}
-
-
-/* suck_start ******************************************************************
-
-   Returns true if classbuffer is already loaded or a file for the
-   specified class has succussfully been read in. All directories of
-   the searchpath are used to find the classfile (<classname>.class).
-   Returns false if no classfile is found and writes an error message.
-       
-*******************************************************************************/
-
-classbuffer *suck_start(classinfo *c)
-{
-       classpath_info *cpi;
-       char           *filename;
-       s4             filenamelen;
-       char *path;
-       FILE *classfile;
-       bool found;
-       s4 len;
-       struct stat buffer;
-       classbuffer *cb;
-
-       /* initialize return value */
+       list_classpath_entry    *lce;
+       hashtable               *ht;
+       s4                       slot;
+       hashtable_zipfile_entry *htzfe;
+       utf                     *u;
 
-       found = false;
-       cb = NULL;
+       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 */
 
-       filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
-       filename = MNEW(char, filenamelen);
+                       ht = lce->htclasses;
 
-       utf_sprint(filename, c->name);
-       strcat(filename, ".class");
+                       for (slot = 0; slot < ht->size; slot++) {
+                               htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
 
-       /* walk through all classpath entries */
+                               for (; htzfe; htzfe = htzfe->hashlink) {
+                                       u = htzfe->filename;
 
-       for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
-#if defined(USE_ZLIB)
-               if (cpi->type == CLASSPATH_ARCHIVE) {
+                                       /* skip all entries in META-INF and .properties,
+                       .png files */
 
-#if defined(USE_THREADS)
-                       /* enter a monitor on zip/jar archives */
-
-                       builtin_monitorenter((java_objectheader *) cpi);
-#endif
-
-                       if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
-                               unz_file_info file_info;
+                                       if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
+                                               strstr(u->text, ".properties") ||
+                                               strstr(u->text, ".png"))
+                                               continue;
 
-                               if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
-                                                                                 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
-                                       if (unzOpenCurrentFile(cpi->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;
-                                               cb->path  = cpi->path;
+                                       /* load class from bootstrap classloader */
 
-                                               len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
+                                       if (!load_class_bootstrap(u)) {
+                                               fprintf(stderr, "Error loading: ");
+                                               utf_fprint_classname(stderr, u);
+                                               fprintf(stderr, "\n");
 
-                                               if (len != cb->size) {
-                                                       suck_stop(cb);
-                                                       log_text("Error while unzipping");
+                                               /* print out exception and cause */
 
-                                               } else {
-                                                       found = true;
-                                               }
-
-                                       } else {
-                                               log_text("Error while opening file in archive");
+                                               exceptions_print_exception(*exceptionptr);
                                        }
-
-                               } else {
-                                       log_text("Error while retrieving fileinfo");
                                }
                        }
-                       unzCloseCurrentFile(cpi->uf);
-
-#if defined(USE_THREADS)
-                       /* leave the monitor */
-
-                       builtin_monitorexit((java_objectheader *) cpi);
-#endif
 
                } else {
-#endif /* defined(USE_ZLIB) */
-                       
-                       path = MNEW(char, cpi->pathlen + filenamelen);
-                       strcpy(path, cpi->path);
-                       strcat(path, filename);
-
-                       classfile = fopen(path, "r");
-
-                       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;
-                                       cb->path  = cpi->path;
-
-                                       /* 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;
-                                       }
-                               }
-                       }
-
-                       MFREE(path, char, cpi->pathlen + filenamelen);
-#if defined(USE_ZLIB)
+#endif
+#if defined(ENABLE_ZLIB)
                }
 #endif
        }
-
-       if (opt_verbose)
-               if (!found) {
-                       dolog("Warning: Can not open class file '%s'", filename);
-
-                       if (strcmp(filename, "org/mortbay/util/MultiException.class") == 0) {
-                               static int i = 0;
-                               i++;
-                               if (i == 3)
-                                       assert(0);
-                       }
-               }
-
-       MFREE(filename, char, filenamelen);
-
-       return cb;
-}
-
-
-/************************** function suck_stop *********************************
-
-       frees memory for buffer with classfile data.
-       Caution: this function may only be called if buffer has been allocated
-                by suck_start with reading a file
-       
-*******************************************************************************/
-
-void suck_stop(classbuffer *cb)
-{
-       /* free memory */
-
-       MFREE(cb->data, u1, cb->size);
-       FREE(cb, classbuffer);
-}
-
-
-/******************************************************************************/
-/******************* Some support functions ***********************************/
-/******************************************************************************/
-
-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");
-}
-
-
-/********** internal function: printflags  (only for debugging) ***************/
-
-void printflags(u2 f)
-{
-       fprintflags(stdout,f);
 }
 
 
-/********************** 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.
        
 *******************************************************************************/
 
@@ -768,15 +300,15 @@ static bool skipattributebody(classbuffer *cb)
 {
        u4 len;
 
-       if (!check_classbuffer_size(cb, 4))
+       if (!suck_check_classbuffer_size(cb, 4))
                return false;
 
        len = suck_u4(cb);
 
-       if (!check_classbuffer_size(cb, len))
+       if (!suck_check_classbuffer_size(cb, len))
                return false;
 
-       skip_nbytes(cb, len);
+       suck_skip_nbytes(cb, len);
 
        return true;
 }
@@ -794,16 +326,16 @@ static bool skipattributes(classbuffer *cb, u4 num)
        u4 len;
 
        for (i = 0; i < num; i++) {
-               if (!check_classbuffer_size(cb, 2 + 4))
+               if (!suck_check_classbuffer_size(cb, 2 + 4))
                        return false;
 
                suck_u2(cb);
                len = suck_u4(cb);
 
-               if (!check_classbuffer_size(cb, len))
+               if (!suck_check_classbuffer_size(cb, len))
                        return false;
 
-               skip_nbytes(cb, len);
+               suck_skip_nbytes(cb, len);
        }
 
        return true;
@@ -878,7 +410,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
        c = cb->class;
 
        /* number of entries in the constant_pool table plus one */
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                return false;
 
        cpcount = c->cpcount = suck_u2(cb);
@@ -888,11 +420,11 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
        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
@@ -913,7 +445,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                u4 t;
 
                /* get constant type */
-               if (!check_classbuffer_size(cb, 1))
+               if (!suck_check_classbuffer_size(cb, 1))
                        return false;
 
                t = suck_u1(cb);
@@ -927,7 +459,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 
                        nfc->thisindex = idx;
                        /* reference to CONSTANT_NameAndType */
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        nfc->name_index = suck_u2(cb);
@@ -944,7 +476,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                        nfs->thisindex = idx;
 
                        /* reference to CONSTANT_Utf8_info with string characters */
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        nfs->string_index = suck_u2(cb);
@@ -960,7 +492,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                                
                        nfn->thisindex = idx;
 
-                       if (!check_classbuffer_size(cb, 2 + 2))
+                       if (!suck_check_classbuffer_size(cb, 2 + 2))
                                return false;
 
                        /* reference to CONSTANT_Utf8_info containing simple name */
@@ -985,7 +517,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                        /* constant type */
                        nff->tag = t;
 
-                       if (!check_classbuffer_size(cb, 2 + 2))
+                       if (!suck_check_classbuffer_size(cb, 2 + 2))
                                return false;
 
                        /* class or interface type that contains the declaration of the
@@ -1001,12 +533,12 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                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
 
-                       if (!check_classbuffer_size(cb, 4))
+                       if (!suck_check_classbuffer_size(cb, 4))
                                return false;
 
                        ci->value = suck_s4(cb);
@@ -1020,12 +552,12 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                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
 
-                       if (!check_classbuffer_size(cb, 4))
+                       if (!suck_check_classbuffer_size(cb, 4))
                                return false;
 
                        cf->value = suck_float(cb);
@@ -1039,12 +571,12 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                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
 
-                       if (!check_classbuffer_size(cb, 8))
+                       if (!suck_check_classbuffer_size(cb, 8))
                                return false;
 
                        cl->value = suck_s8(cb);
@@ -1052,8 +584,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                        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;
@@ -1062,12 +593,12 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                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
 
-                       if (!check_classbuffer_size(cb, 8))
+                       if (!suck_check_classbuffer_size(cb, 8))
                                return false;
 
                        cd->value = suck_double(cb);
@@ -1075,8 +606,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                        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;
@@ -1086,37 +616,35 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                        u4 length;
 
                        /* number of bytes in the bytes array (not string-length) */
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        length = suck_u2(cb);
                        cptags[idx] = CONSTANT_Utf8;
 
                        /* validate the string */
-                       if (!check_classbuffer_size(cb, length))
+                       if (!suck_check_classbuffer_size(cb, length))
                                return false;
 
 #ifdef ENABLE_VERIFIER
                        if (opt_verify &&
-                               !is_valid_utf((char *) (cb->pos + 1),
-                                                         (char *) (cb->pos + 1 + length))) 
+                               !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 */
                        /* insert utf-string into the utf-symboltable */
-                       cpinfos[idx] = utf_new((char *) (cb->pos + 1), length);
+                       cpinfos[idx] = utf_new((char *) cb->pos, length);
 
                        /* skip bytes of the string (buffer size check above) */
-                       skip_nbytes(cb, length);
+                       suck_skip_nbytes(cb, length);
                        idx++;
                        break;
                }
                                                                                
                default:
-                       *exceptionptr =
-                               new_classformaterror(c, "Illegal constant pool type");
+                       exceptions_throw_classformaterror(c, "Illegal constant pool type");
                        return false;
                }  /* end switch */
        } /* end while */
@@ -1132,8 +660,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 
 #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 */
@@ -1180,7 +707,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
        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
@@ -1202,18 +729,16 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                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;
                        }
                }
@@ -1230,7 +755,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                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
@@ -1286,7 +811,7 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
 
        c = cb->class;
 
-       if (!check_classbuffer_size(cb, 2 + 2 + 2))
+       if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
                return false;
 
        f->flags = suck_u2(cb);
@@ -1305,10 +830,10 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
        if (!descriptor_pool_add(descpool, u, NULL))
                return false;
 
-       /* descriptor_pool_add accepts method descriptors, so we have to check */
-       /* against them here before the call of desc_to_type below.            */
+       /* 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;
        }
 
@@ -1316,9 +841,9 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
        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;
                }
 
@@ -1327,10 +852,9 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
 
                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;
                }
 
@@ -1338,18 +862,17 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
                        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 = desc_to_type(f->descriptor);    /* data type            */
-       f->offset = 0;                             /* offset from start of object */
+       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;
        
@@ -1367,33 +890,30 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
        }
 
        /* read attributes */
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                return false;
 
        attrnum = suck_u2(cb);
        for (i = 0; i < attrnum; i++) {
-               if (!check_classbuffer_size(cb, 2))
+               if (!suck_check_classbuffer_size(cb, 2))
                        return false;
 
                if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                        return false;
 
                if (u == utf_ConstantValue) {
-                       if (!check_classbuffer_size(cb, 4 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                return false;
 
                        /* 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;
                        }
                        
@@ -1491,7 +1011,7 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
        initObjectLock(&m->header);
 #endif
 
-#ifdef STATISTICS
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
                count_all_methods++;
 #endif
@@ -1502,7 +1022,7 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
        m->class = c;
        m->nativelyoverloaded = false;
        
-       if (!check_classbuffer_size(cb, 2 + 2 + 2))
+       if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
                return false;
 
        m->flags = suck_u2(cb);
@@ -1524,13 +1044,13 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
 #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;
                }
        }
@@ -1542,8 +1062,7 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
 #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;
                }
 
@@ -1552,30 +1071,27 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
                        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;
                                }
                        }
@@ -1583,8 +1099,7 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
                        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;
                                }
                        }
@@ -1611,14 +1126,14 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
 
        m->xta = NULL;
 
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_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))
+               if (!suck_check_classbuffer_size(cb, 2))
                        return false;
 
                if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
@@ -1626,21 +1141,16 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
 
                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;
                        }
 
-                       if (!check_classbuffer_size(cb, 4 + 2 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
                                return false;
 
                        suck_u4(cb);
@@ -1648,48 +1158,41 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
                        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;
                        }
                        
-                       if (!check_classbuffer_size(cb, 4))
+                       if (!suck_check_classbuffer_size(cb, 4))
                                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;
                        }
 
-                       if (!check_classbuffer_size(cb, m->jcodelength))
+                       if (!suck_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))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        m->exceptiontablelength = suck_u2(cb);
-                       if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
+                       if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
                                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 +=
@@ -1715,7 +1218,7 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
                                }
                        }
 
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        codeattrnum = suck_u2(cb);
@@ -1723,7 +1226,7 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
                        for (; codeattrnum > 0; codeattrnum--) {
                                utf *caname;
 
-                               if (!check_classbuffer_size(cb, 2))
+                               if (!suck_check_classbuffer_size(cb, 2))
                                        return false;
 
                                if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
@@ -1732,13 +1235,13 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
                                if (caname == utf_LineNumberTable) {
                                        u2 lncid;
 
-                                       if (!check_classbuffer_size(cb, 4 + 2))
+                                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                                return false;
 
                                        suck_u4(cb);
                                        m->linenumbercount = suck_u2(cb);
 
-                                       if (!check_classbuffer_size(cb,
+                                       if (!suck_check_classbuffer_size(cb,
                                                                                                (2 + 2) * m->linenumbercount))
                                                return false;
 
@@ -1765,18 +1268,17 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
                        s4 j;
 
                        if (m->thrownexceptions) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Multiple Exceptions attributes");
+                               exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
                                return false;
                        }
 
-                       if (!check_classbuffer_size(cb, 4 + 2))
+                       if (!suck_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))
+                       if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
                                return false;
 
                        m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
@@ -1795,8 +1297,7 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
        }
 
        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;
        }
 
@@ -1822,7 +1323,7 @@ static bool load_attributes(classbuffer *cb, u4 num)
 
        for (i = 0; i < num; i++) {
                /* retrieve attribute name */
-               if (!check_classbuffer_size(cb, 2))
+               if (!suck_check_classbuffer_size(cb, 2))
                        return false;
 
                if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
@@ -1831,12 +1332,11 @@ static bool load_attributes(classbuffer *cb, u4 num)
                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;
                        }
                                
-                       if (!check_classbuffer_size(cb, 4 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                return false;
 
                        /* skip attribute length */
@@ -1845,7 +1345,7 @@ static bool load_attributes(classbuffer *cb, u4 num)
                        /* number of records */
                        c->innerclasscount = suck_u2(cb);
 
-                       if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
+                       if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
                                return false;
 
                        /* allocate memory for innerclass structure */
@@ -1870,18 +1370,16 @@ static bool load_attributes(classbuffer *cb, u4 num)
                        }
 
                } else if (aname == utf_SourceFile) {
-                       if (!check_classbuffer_size(cb, 4 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                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;
                        }
 
@@ -1920,7 +1418,7 @@ classinfo *load_class_from_sysloader(utf *name)
 
        LOADER_ASSERT(class_java_lang_Object);
        LOADER_ASSERT(class_java_lang_ClassLoader);
-       LOADER_ASSERT(class_java_lang_ClassLoader->linked);
+       LOADER_ASSERT(class_java_lang_ClassLoader->state & CLASS_LINKED);
        
        m = class_resolveclassmethod(class_java_lang_ClassLoader,
                                                                 utf_getSystemClassLoader,
@@ -1931,7 +1429,7 @@ classinfo *load_class_from_sysloader(utf *name)
        if (!m)
                return false;
 
-       cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
+       ASM_CALLJAVAFUNCTION_ADR(cl, m, NULL, NULL, NULL, NULL);
 
        if (!cl)
                return false;
@@ -1958,8 +1456,9 @@ classinfo *load_class_from_sysloader(utf *name)
 
 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
 {
-       classinfo *c;
-       classinfo *tmpc;
+       java_objectheader *o;
+       classinfo         *c;
+       classinfo         *tmpc;
 
        LOADER_ASSERT(name);
 
@@ -2006,7 +1505,7 @@ classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
 
                                if (tmpc == NULL) {
                                        /* exception, free the loaded class */
-                                       c->loaded = false;
+                                       c->state &= ~CLASS_LOADING;
                                        class_free(c);
                                }
 
@@ -2028,7 +1527,7 @@ classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
 
                                if (tmpc == NULL) {
                                        /* exception, free the loaded class */
-                                       c->loaded = false;
+                                       c->state &= ~CLASS_LOADING;
                                        class_free(c);
                                }
 
@@ -2054,10 +1553,13 @@ classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
                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* */
+
+               ASM_CALLJAVAFUNCTION_ADR(o, lc, cl,
+                                                                javastring_new_slash_to_dot(name),
+                                                                NULL, NULL);
+
+               c = (classinfo *) o;
 
                if (c) {
                        /* Store this class in the loaded class cache. If another
@@ -2071,7 +1573,7 @@ classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
 
                        if (tmpc == NULL) {
                                /* exception, free the loaded class */
-                               c->loaded = false;
+                               c->state &= ~CLASS_LOADING;
                                class_free(c);
                        }
 
@@ -2145,11 +1647,11 @@ classinfo *load_class_bootstrap(utf *name)
                c = load_newly_created_array(c, NULL);
                if (c == NULL)
                        return NULL;
-               LOADER_ASSERT(c->loaded);
+               LOADER_ASSERT(c->state & CLASS_LOADED);
                return c;
        }
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        /* measure time */
 
        if (getcompilingtime)
@@ -2168,9 +1670,7 @@ classinfo *load_class_bootstrap(utf *name)
                        throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
                                                                           "java/lang/Object");
 
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
-                                                                        name);
+               *exceptionptr = new_noclassdeffounderror(name);
 
                return NULL;
        }
@@ -2211,7 +1711,7 @@ classinfo *load_class_bootstrap(utf *name)
 
        suck_stop(cb);
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        /* measure time */
 
        if (getloadingtime)
@@ -2250,7 +1750,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        u4 ma, mi;
        s4 dumpsize;
        descriptor_pool *descpool;
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        u4 classrefsize;
        u4 descsize;
 #endif
@@ -2259,36 +1759,38 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
 
        c = cb->class;
 
-       /* maybe the class is already loaded */
+       /* the class is already loaded */
 
-       if (c->loaded)
+       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();
 
-       /* class is somewhat loaded */
+       /* class is currently loading */
 
-       c->loaded = true;
+       c->state |= CLASS_LOADING;
 
-       if (!check_classbuffer_size(cb, 4 + 2 + 2))
+       if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
                goto return_exception;
 
        /* check signature */
 
        if (suck_u4(cb) != MAGIC) {
-               *exceptionptr = new_classformaterror(c, "Bad magic number");
+               exceptions_throw_classformaterror(c, "Bad magic number");
 
                goto return_exception;
        }
@@ -2316,16 +1818,12 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        if (!load_constantpool(cb, descpool))
                goto return_exception;
 
-       /*JOWENN*/
-       c->erroneous_state = 0;
-       c->initializing_thread = 0;     
-       /*JOWENN*/
        c->classUsed = NOTUSED; /* not used initially CO-RT */
        c->impldBy = NULL;
 
        /* ACC flags */
 
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        c->flags = suck_u2(cb);
@@ -2341,10 +1839,9 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                }
 
                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;
                }
 
@@ -2354,13 +1851,13 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        }
 
        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;
        }
 
-       if (!check_classbuffer_size(cb, 2 + 2))
+       if (!suck_check_classbuffer_size(cb, 2 + 2))
                goto return_exception;
 
        /* this class */
@@ -2430,20 +1927,19 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                /* 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 (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        c->interfacescount = suck_u2(cb);
 
-       if (!check_classbuffer_size(cb, 2 * c->interfacescount))
+       if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
                goto return_exception;
 
        c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
@@ -2454,7 +1950,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        }
 
        /* load fields */
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        c->fieldscount = suck_u2(cb);
@@ -2466,7 +1962,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        }
 
        /* load methods */
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        c->methodscount = suck_u2(cb);
@@ -2488,7 +1984,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        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;
@@ -2649,10 +2145,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                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]));
@@ -2683,10 +2176,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                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]));
@@ -2698,17 +2188,17 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        }
 #endif /* ENABLE_VERIFIER */
 
-#if defined(STATISTICS)
+#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(fieldinfo)  * c->fieldscount;
                count_class_infos += sizeof(methodinfo) * c->methodscount;
        }
 #endif
 
        /* load attribute structures */
 
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        if (!load_attributes(cb, suck_u2(cb)))
@@ -2721,11 +2211,10 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
         */
        if ((ma == 45 && mi > 3) || ma > 45) {
                /* check if all data has been read */
-               s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
+               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;
                }
        }
@@ -2734,9 +2223,15 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        /* release dump area */
 
        dump_release(dumpsize);
-       
+
+       /* revert loading state and class is loaded */
+
+       c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
+
+#if !defined(NDEBUG)
        if (loadverbose)
                log_message_class("Loading done class: ", c);
+#endif
 
        return c;
 
@@ -2799,7 +2294,7 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
                if (!(comp = load_class_from_classloader(u, loader)))
                        return NULL;
 
-               LOADER_ASSERT(comp->loaded);
+               LOADER_ASSERT(comp->state & CLASS_LOADED);
 
                if (opt_eager)
                        if (!link_class(c))
@@ -2824,7 +2319,7 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
                if (!(comp = load_class_from_classloader(u, loader)))
                        return NULL;
 
-               LOADER_ASSERT(comp->loaded);
+               LOADER_ASSERT(comp->state & CLASS_LOADED);
 
                if (opt_eager)
                        if (!link_class(c))
@@ -2864,12 +2359,12 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
                classinfo *tc;
 
                tc = class_java_lang_Cloneable;
-               LOADER_ASSERT(tc->loaded);
+               LOADER_ASSERT(tc->state & CLASS_LOADED);
                list_addfirst(&unlinkedclasses, tc);
                c->interfaces[0].cls = tc;
 
                tc = class_java_io_Serializable;
-               LOADER_ASSERT(tc->loaded);
+               LOADER_ASSERT(tc->state & CLASS_LOADED);
                list_addfirst(&unlinkedclasses, tc);
                c->interfaces[1].cls = tc;
 
@@ -2927,7 +2422,7 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
 
        /* array classes are not loaded from class files */
 
-       c->loaded = true;
+       c->state |= CLASS_LOADED;
        c->parseddescs = (u1 *) clonedesc;
        c->parseddescsize = sizeof(methodinfo);
        c->classrefs = classrefs;