* Merged with 3aaaa9f60c5d.
[cacao.git] / src / vm / builtin.c
index ad419deb6ec32f3bd4a074fee64833cbfe86e251..23588740155e7dfbcec5a2bee2948b2fdd371632 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/builtin.c - functions for unsupported operations
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-            Andreas Krall
-            Mark Probst
-
-   Changes: Christian Thalinger
-            Edwin Steiner
-
    Contains C functions for JavaVM Instructions that cannot be
    translated to machine language directly. Consequently, the
    generated machine code for these instructions contains function
    calls instead of machine instructions, using the C calling
    convention.
 
-   $Id: builtin.c 6013 2006-11-16 22:14:10Z twisti $
-
 */
 
 
@@ -46,7 +35,6 @@
 
 #include <assert.h>
 #include <errno.h>
-#include <math.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/time.h>
 #include "mm/gc-common.h"
 #include "mm/memory.h"
 
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "native/jni.h"
+#include "native/llni.h"
+
+#include "threads/lock-common.h"
+#include "threads/threads-common.h"
 
 #include "toolbox/logging.h"
 #include "toolbox/util.h"
+
+#include "vm/array.h"
 #include "vm/builtin.h"
-#include "vm/class.h"
+#include "vm/cycles-stats.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/initialize.h"
-#include "vm/loader.h"
-#include "vm/options.h"
+#include "vm/primitive.h"
 #include "vm/stringlocal.h"
+
 #include "vm/jit/asmpart.h"
-#include "vm/jit/patcher.h"
-#include "vm/rt-timing.h"
-#include "vm/cycles-stats.h"
+#include "vm/jit/trace.h"
 
+#include "vmcore/class.h"
+#include "vmcore/linker.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vmcore/rt-timing.h"
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+#if defined(ENABLE_DEBUG_FILTER)
+#      include "vm/jit/show.h"
+#endif
 
 /* include builtin tables *****************************************************/
 
@@ -165,26 +168,45 @@ static bool builtintable_init(void)
 
        descriptor_pool_alloc_parsed_descriptors(descpool);
 
-       /* now parse all descriptors */
+       /* Now parse all descriptors.  NOTE: builtin-functions are treated
+          like static methods (no `this' pointer). */
 
        for (bte = builtintable_internal; bte->fp != NULL; bte++) {
-               /* parse the descriptor, builtin is always static (no `this' pointer) */
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+
+               /* generate a builtin stub if we need one */
 
-               bte->md = descriptor_pool_parse_method_descriptor(descpool,
-                                                                                                                 bte->descriptor,
-                                                                                                                 ACC_STATIC, NULL);
+               if (bte->flags & BUILTINTABLE_FLAG_STUB)
+                       codegen_generate_stub_builtin(bte);
        }
 
        for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
-               bte->md = descriptor_pool_parse_method_descriptor(descpool,
-                                                                                                                 bte->descriptor,
-                                                                                                                 ACC_STATIC, NULL);
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+
+               /* no stubs should be needed for this table */
+
+               assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
        }
 
        for (bte = builtintable_function; bte->fp != NULL; bte++) {
-               bte->md = descriptor_pool_parse_method_descriptor(descpool,
-                                                                                                                 bte->descriptor,
-                                                                                                                 ACC_STATIC, NULL);
+               bte->md =
+                       descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                       bte->descriptor,
+                                                                                                       ACC_STATIC | ACC_METHOD_BUILTIN,
+                                                                                                       NULL);
+
+               /* generate a builtin stub if we need one */
+
+               if (bte->flags & BUILTINTABLE_FLAG_STUB)
+                       codegen_generate_stub_builtin(bte);
        }
 
        /* release dump area */
@@ -302,7 +324,8 @@ builtintable_entry *builtintable_get_automatic(s4 opcode)
                if (middle->opcode < opcode) {
                        first = middle + 1;
                        entries -= half + 1;
-               } else
+               }
+               else
                        entries = half;
        }
 
@@ -316,10 +339,14 @@ builtintable_entry *builtintable_get_automatic(s4 opcode)
 
 *******************************************************************************/
 
-bool builtintable_replace_function(instruction *iptr)
+#if defined(ENABLE_JIT)
+bool builtintable_replace_function(void *iptr_)
 {
        constant_FMIref    *mr;
        builtintable_entry *bte;
+       instruction        *iptr;
+
+       iptr = (instruction *) iptr_; /* twisti will kill me ;) */
 
        /* get name and descriptor of the function */
 
@@ -343,14 +370,15 @@ bool builtintable_replace_function(instruction *iptr)
 
        for (bte = builtintable_function; bte->fp != NULL; bte++) {
                if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
-                       (mr->name             == bte->name) &&
-                       (mr->descriptor       == bte->descriptor)) {
+                       (mr->name                == bte->name) &&
+                       (mr->descriptor          == bte->descriptor)) {
 
                        /* set the values in the instruction */
 
-                       iptr->opc   = bte->opcode;
+                       iptr->opc           = bte->opcode;
                        iptr->sx.s23.s3.bte = bte;
-                       if (bte->checkexception)
+
+                       if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
                                iptr->flags.bits |= INS_FLAG_CHECK;
                        else
                                iptr->flags.bits &= ~INS_FLAG_CHECK;
@@ -361,112 +389,55 @@ bool builtintable_replace_function(instruction *iptr)
 
        return false;
 }
+#endif /* defined(ENABLE_JIT) */
 
 
 /*****************************************************************************
                                                                TYPE CHECKS
 *****************************************************************************/
 
+/* builtin_instanceof **********************************************************
 
+   Checks if an object is an instance of some given class (or subclass
+   of that class). If class is an interface, checks if the interface
+   is implemented.
 
-/*************** internal function: builtin_isanysubclass *********************
-
-       Checks a subclass relation between two classes. Implemented interfaces
-       are interpreted as super classes.
-       Return value:  1 ... sub is subclass of super
-                                  0 ... otherwise
-
-******************************************************************************/
-
-s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
-{
-       s4 res;
-       castinfo classvalues;
-
-       if (sub == super)
-               return 1;
-
-       if (super->flags & ACC_INTERFACE) {
-               res = (sub->vftbl->interfacetablelength > super->index) &&
-                       (sub->vftbl->interfacetable[-super->index] != NULL);
-
-       } else {
-               /* java.lang.Object is the only super_class_ of any interface */
-               if (sub->flags & ACC_INTERFACE)
-                       return (super == class_java_lang_Object);
-
-               ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
-
-               res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
-                       (u4) classvalues.super_diffval;
-       }
-
-       return res;
-}
-
-
-s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
-{
-       s4 res;
-       s4 base;
-       castinfo classvalues;
-
-       if (sub == super)
-               return 1;
-
-       ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
-
-       if ((base = classvalues.super_baseval) <= 0) {
-               /* super is an interface */
-               res = (sub->interfacetablelength > -base) &&
-                       (sub->interfacetable[base] != NULL);
-       } 
-       else {
-               /* java.lang.Object is the only super_class_ of any interface */
-               if (classvalues.sub_baseval <= 0)
-                       return classvalues.super_baseval == 1;
-
-           res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
-                       <= (u4) classvalues.super_diffval;
-       }
-
-       return res;
-}
-
-
-/****************** function: builtin_instanceof *****************************
-
-       Checks if an object is an instance of some given class (or subclass of
-       that class). If class is an interface, checks if the interface is
-       implemented.
-       Return value:  1 ... obj is an instance of class or implements the interface
-                                  0 ... otherwise or if obj == NULL
+   Return value: 1 ... o is an instance of class or implements the interface
+                 0 ... otherwise or if o == NULL
                         
-*****************************************************************************/
+*******************************************************************************/
 
-s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
+s4 builtin_instanceof(java_handle_t *o, classinfo *class)
 {
-       if (!obj)
+       classinfo *c;
+
+       if (o == NULL)
                return 0;
 
-       return builtin_isanysubclass(obj->vftbl->class, class);
+       LLNI_class_get(o, c);
+
+       return class_isanysubclass(c, class);
 }
 
 
 
-/**************** function: builtin_checkcast *******************************
+/* builtin_checkcast ***********************************************************
 
-       The same as builtin_instanceof except that 1 is returned when
-       obj == NULL
+   The same as builtin_instanceof except that 1 is returned when o ==
+   NULL.
                          
-****************************************************************************/
+*******************************************************************************/
 
-s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
+s4 builtin_checkcast(java_handle_t *o, classinfo *class)
 {
-       if (obj == NULL)
+       classinfo *c;
+
+       if (o == NULL)
                return 1;
 
-       if (builtin_isanysubclass(obj->vftbl->class, class))
+       LLNI_class_get(o, c);
+
+       if (class_isanysubclass(c, class))
                return 1;
 
        return 0;
@@ -504,8 +475,8 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc,
                        (target->elementvftbl->baseval == 1))
                        return 1;
 
-               return builtin_isanysubclass_vftbl(desc->elementvftbl,
-                                                                                  target->elementvftbl);
+               return class_isanysubclass(desc->elementvftbl->class,
+                                                                  target->elementvftbl->class);
        }
 
        if (desc->dimension < target->dimension)
@@ -513,8 +484,8 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc,
 
        /* {desc has higher dimension than target} */
 
-       return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
-                                                                          target->elementvftbl);
+       return class_isanysubclass(pseudo_class_Arraystub,
+                                                          target->elementvftbl->class);
 }
 
 
@@ -531,23 +502,25 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc,
        
 *******************************************************************************/
 
-s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
+s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass)
 {
        arraydescriptor *desc;
 
-       if (!o)
+       if (o == NULL)
                return 1;
 
-       if ((desc = o->vftbl->arraydesc) == NULL)
+       desc = LLNI_vftbl_direct(o)->arraydesc;
+
+       if (desc == NULL)
                return 0;
  
        return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
 }
 
 
-s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
+s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass)
 {
-       if (!o)
+       if (o == NULL)
                return 0;
 
        return builtin_arraycheckcast(o, targetclass);
@@ -561,70 +534,18 @@ s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
 
 *******************************************************************************/
 
-void *builtin_throw_exception(java_objectheader *xptr)
+void *builtin_throw_exception(java_object_t *xptr)
 {
 #if !defined(NDEBUG)
-    java_lang_Throwable *t;
-       char                *logtext;
-       s4                   logtextlen;
-       s4                   dumpsize;
-
-       if (opt_verbose) {
-               t = (java_lang_Throwable *) xptr;
-
-               /* calculate message length */
-
-               logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
-
-               if (t) {
-                       logtextlen +=
-                               utf_bytes(xptr->vftbl->class->name);
-                       if (t->detailMessage) {
-                               logtextlen += strlen(": ") +
-                                       u2_utflength(t->detailMessage->value->data 
-                                                                       + t->detailMessage->offset,
-                                                        t->detailMessage->count);
-                       }
-               } 
-               else {
-                       logtextlen += strlen("(nil)");
-               }
-
-               /* allocate memory */
-
-               dumpsize = dump_size();
-
-               logtext = DMNEW(char, logtextlen);
-
-               strcpy(logtext, "Builtin exception thrown: ");
+       /* print exception trace */
 
-               if (t) {
-                       utf_cat_classname(logtext, xptr->vftbl->class->name);
-
-                       if (t->detailMessage) {
-                               char *buf;
-
-                               buf = javastring_tochar((java_objectheader *) t->detailMessage);
-                               strcat(logtext, ": ");
-                               strcat(logtext, buf);
-                               MFREE(buf, char, strlen(buf) + 1);
-                       }
-
-               } else {
-                       strcat(logtext, "(nil)");
-               }
-
-               log_text(logtext);
-
-               /* release memory */
-
-               dump_release(dumpsize);
-       }
+       if (opt_TraceExceptions)
+               trace_exception_builtin(xptr);
 #endif /* !defined(NDEBUG) */
 
        /* actually set the exception */
 
-       *exceptionptr = xptr;
+       exceptions_set_exception(xptr);
 
        /* Return a NULL pointer.  This is required for vm_call_method to
           check for an exception.  This is for convenience. */
@@ -638,20 +559,40 @@ void *builtin_throw_exception(java_objectheader *xptr)
    Checks, if an object can be stored in an array.
 
    Return value: 1 ... possible
-                 0 ... otherwise
+                 0 ... otherwise (throws an ArrayStoreException)
 
 *******************************************************************************/
 
-s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
+s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
+{
+       int result;
+
+       LLNI_CRITICAL_START;
+
+       result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
+
+       LLNI_CRITICAL_END;
+
+       /* if not possible, throw an exception */
+
+       if (result == 0)
+               exceptions_throw_arraystoreexception();
+
+       return result;
+}
+
+
+s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
 {
        arraydescriptor *desc;
        arraydescriptor *valuedesc;
        vftbl_t         *componentvftbl;
        vftbl_t         *valuevftbl;
-       s4               base;
-       castinfo         classvalues;
+       int32_t          baseval;
+       uint32_t         diffval;
+       int              result;
 
-       if (!o)
+       if (o == NULL)
                return 1;
 
        /* The following is guaranteed (by verifier checks):
@@ -664,54 +605,64 @@ s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
        desc           = oa->header.objheader.vftbl->arraydesc;
        componentvftbl = desc->componentvftbl;
        valuevftbl     = o->vftbl;
+       valuedesc      = valuevftbl->arraydesc;
 
        if ((desc->dimension - 1) == 0) {
-               s4 res;
-
                /* {oa is a one-dimensional array} */
                /* {oa is an array of references} */
                
                if (valuevftbl == componentvftbl)
                        return 1;
 
-               ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
+               LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+
+               baseval = componentvftbl->baseval;
 
-               if ((base = classvalues.super_baseval) <= 0)
+               if (baseval <= 0) {
                        /* an array of interface references */
-                       return (valuevftbl->interfacetablelength > -base &&
-                                       valuevftbl->interfacetable[base] != NULL);
-               
-               res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
-                          <= (unsigned) classvalues.super_diffval);
 
-               return res;
-       }
+                       result = ((valuevftbl->interfacetablelength > -baseval) &&
+                                         (valuevftbl->interfacetable[baseval] != NULL));
+               }
+               else {
+                       diffval = valuevftbl->baseval - componentvftbl->baseval;
+                       result  = diffval <= (uint32_t) componentvftbl->diffval;
+               }
 
-       /* {oa has dimension > 1} */
-       /* {componentvftbl->arraydesc != NULL} */
+               LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+       }
+       else if (valuedesc == NULL) {
+               /* {oa has dimension > 1} */
+               /* {componentvftbl->arraydesc != NULL} */
 
-       /* check if o is an array */
+               /* check if o is an array */
 
-       if ((valuedesc = valuevftbl->arraydesc) == NULL)
                return 0;
+       }
+       else {
+               /* {o is an array} */
 
-       /* {o is an array} */
+               result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+       }
 
-       return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+       /* return result */
+
+       return result;
 }
 
 
 /* This is an optimized version where a is guaranteed to be one-dimensional */
-s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
+s4 builtin_canstore_onedim (java_objectarray_t *a, java_object_t *o)
 {
        arraydescriptor *desc;
-       vftbl_t *elementvftbl;
-       vftbl_t *valuevftbl;
-       s4 res;
-       int base;
-       castinfo classvalues;
+       vftbl_t         *elementvftbl;
+       vftbl_t         *valuevftbl;
+       int32_t          baseval;
+       uint32_t         diffval;
+       int              result;
        
-       if (!o) return 1;
+       if (o == NULL)
+               return 1;
 
        /* The following is guaranteed (by verifier checks):
         *
@@ -730,30 +681,37 @@ s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
        if (valuevftbl == elementvftbl)
                return 1;
 
-       ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
+       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+
+       baseval = elementvftbl->baseval;
 
-       if ((base = classvalues.super_baseval) <= 0)
+       if (baseval <= 0) {
                /* an array of interface references */
-               return (valuevftbl->interfacetablelength > -base &&
-                               valuevftbl->interfacetable[base] != NULL);
+               result = ((valuevftbl->interfacetablelength > -baseval) &&
+                                 (valuevftbl->interfacetable[baseval] != NULL));
+       }
+       else {
+               diffval = valuevftbl->baseval - elementvftbl->baseval;
+               result  = diffval <= (uint32_t) elementvftbl->diffval;
+       }
 
-       res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
-               <= (unsigned) classvalues.super_diffval;
+       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
 
-       return res;
+       return result;
 }
 
 
 /* This is an optimized version where a is guaranteed to be a
  * one-dimensional array of a class type */
-s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
+s4 builtin_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
 {
-       vftbl_t *elementvftbl;
-       vftbl_t *valuevftbl;
-       s4 res;
-       castinfo classvalues;
+       vftbl_t  *elementvftbl;
+       vftbl_t  *valuevftbl;
+       uint32_t  diffval;
+       int       result;
        
-       if (!o) return 1;
+       if (o == NULL)
+               return 1;
 
        /* The following is guaranteed (by verifier checks):
         *
@@ -772,12 +730,14 @@ s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
        if (valuevftbl == elementvftbl)
                return 1;
 
-       ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
+       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+
+       diffval = valuevftbl->baseval - elementvftbl->baseval;
+       result  = diffval <= (uint32_t) elementvftbl->diffval;
 
-       res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
-               <= (unsigned) classvalues.super_diffval;
+       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
 
-       return res;
+       return result;
 }
 
 
@@ -787,12 +747,12 @@ s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
 
    Return value: pointer to the object or NULL if no memory is
    available
-                       
+
 *******************************************************************************/
 
-java_objectheader *builtin_new(classinfo *c)
+java_handle_t *builtin_new(classinfo *c)
 {
-       java_objectheader *o;
+       java_object_t *o;
 #if defined(ENABLE_RT_TIMING)
        struct timespec time_start, time_end;
 #endif
@@ -810,9 +770,7 @@ java_objectheader *builtin_new(classinfo *c)
        /* check if we can instantiate this class */
 
        if (c->flags & ACC_ABSTRACT) {
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_InstantiationError,
-                                                                        c->name);
+               exceptions_throw_instantiationerror(c);
                return NULL;
        }
 
@@ -832,8 +790,69 @@ java_objectheader *builtin_new(classinfo *c)
                        return NULL;
        }
 
-       o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
-                                         c->finalizer);
+       o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                  c->finalizer, true);
+
+       if (!o)
+               return NULL;
+
+       o->vftbl = c->vftbl;
+
+#if defined(ENABLE_THREADS)
+       lock_init_object_lock(o);
+#endif
+
+       CYCLES_STATS_GET(cycles_end);
+       RT_TIMING_GET_TIME(time_end);
+
+       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+
+       return o;
+}
+
+
+/* builtin_fast_new ************************************************************
+
+   Creates a new instance of class c on the heap.
+
+   Return value: pointer to the object or NULL if no fast return
+   is possible for any reason.
+
+*******************************************************************************/
+
+java_object_t *builtin_fast_new(classinfo *c)
+{
+       java_object_t *o;
+#if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+#endif
+#if defined(ENABLE_CYCLES_STATS)
+       u8 cycles_start, cycles_end;
+#endif
+
+       RT_TIMING_GET_TIME(time_start);
+       CYCLES_STATS_GET(cycles_start);
+
+       /* is the class loaded */
+
+       assert(c->state & CLASS_LOADED);
+
+       /* check if we can instantiate this class */
+
+       if (c->flags & ACC_ABSTRACT)
+               return NULL;
+
+       /* is the class linked */
+
+       if (!(c->state & CLASS_LINKED))
+               return NULL;
+
+       if (!(c->state & CLASS_INITIALIZED))
+               return NULL;
+
+       o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                  c->finalizer, false);
 
        if (!o)
                return NULL;
@@ -863,13 +882,13 @@ java_objectheader *builtin_new(classinfo *c)
 
 *******************************************************************************/
 
-java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
+java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
 {
-       arraydescriptor  *desc;
-       s4                dataoffset;
-       s4                componentsize;
-       s4                actualsize;
-       java_arrayheader *a;
+       arraydescriptor *desc;
+       s4               dataoffset;
+       s4               componentsize;
+       s4               actualsize;
+       java_array_t    *a;
 #if defined(ENABLE_RT_TIMING)
        struct timespec time_start, time_end;
 #endif
@@ -887,14 +906,16 @@ java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
 
        actualsize = dataoffset + size * componentsize;
 
-       if (((u4) actualsize) < ((u4) size)) { /* overflow */
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
+       /* check for overflow */
+
+       if (((u4) actualsize) < ((u4) size)) {
+               exceptions_throw_outofmemoryerror();
                return NULL;
        }
 
-       a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
+       a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
 
-       if (!a)
+       if (a == NULL)
                return NULL;
 
        a->objheader.vftbl = arrayclass->vftbl;
@@ -903,7 +924,7 @@ java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
        lock_init_object_lock(&a->objheader);
 #endif
 
-       a->size = size;
+       LLNI_array_size(a) = size;
 
        RT_TIMING_GET_TIME(time_end);
        RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
@@ -921,7 +942,7 @@ java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
 
 *******************************************************************************/
 
-java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
+java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
 {
        classinfo *arrayclass;
        
@@ -940,7 +961,7 @@ java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
        if (!arrayclass)
                return NULL;
 
-       return (java_objectarray *) builtin_newarray(size, arrayclass);
+       return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
 }
 
 
@@ -954,9 +975,9 @@ java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
 
 *******************************************************************************/
 
-java_booleanarray *builtin_newarray_boolean(s4 size)
+java_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
 {
-       return (java_booleanarray *)
+       return (java_handle_booleanarray_t *)
                builtin_newarray(size,
                                                 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
 }
@@ -971,9 +992,9 @@ java_booleanarray *builtin_newarray_boolean(s4 size)
 
 *******************************************************************************/
 
-java_bytearray *builtin_newarray_byte(s4 size)
+java_handle_bytearray_t *builtin_newarray_byte(s4 size)
 {
-       return (java_bytearray *)
+       return (java_handle_bytearray_t *)
                builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
 }
 
@@ -987,9 +1008,9 @@ java_bytearray *builtin_newarray_byte(s4 size)
 
 *******************************************************************************/
 
-java_chararray *builtin_newarray_char(s4 size)
+java_handle_chararray_t *builtin_newarray_char(s4 size)
 {
-       return (java_chararray *)
+       return (java_handle_chararray_t *)
                builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
 }
 
@@ -1003,9 +1024,9 @@ java_chararray *builtin_newarray_char(s4 size)
 
 *******************************************************************************/
 
-java_shortarray *builtin_newarray_short(s4 size)
+java_handle_shortarray_t *builtin_newarray_short(s4 size)
 {
-       return (java_shortarray *)
+       return (java_handle_shortarray_t *)
                builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
 }
 
@@ -1019,9 +1040,9 @@ java_shortarray *builtin_newarray_short(s4 size)
 
 *******************************************************************************/
 
-java_intarray *builtin_newarray_int(s4 size)
+java_handle_intarray_t *builtin_newarray_int(s4 size)
 {
-       return (java_intarray *)
+       return (java_handle_intarray_t *)
                builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
 }
 
@@ -1035,9 +1056,9 @@ java_intarray *builtin_newarray_int(s4 size)
 
 *******************************************************************************/
 
-java_longarray *builtin_newarray_long(s4 size)
+java_handle_longarray_t *builtin_newarray_long(s4 size)
 {
-       return (java_longarray *)
+       return (java_handle_longarray_t *)
                builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
 }
 
@@ -1051,9 +1072,9 @@ java_longarray *builtin_newarray_long(s4 size)
 
 *******************************************************************************/
 
-java_floatarray *builtin_newarray_float(s4 size)
+java_handle_floatarray_t *builtin_newarray_float(s4 size)
 {
-       return (java_floatarray *)
+       return (java_handle_floatarray_t *)
                builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
 }
 
@@ -1067,9 +1088,9 @@ java_floatarray *builtin_newarray_float(s4 size)
 
 *******************************************************************************/
 
-java_doublearray *builtin_newarray_double(s4 size)
+java_handle_doublearray_t *builtin_newarray_double(s4 size)
 {
-       return (java_doublearray *)
+       return (java_handle_doublearray_t *)
                builtin_newarray(size,
                                                 primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
 }
@@ -1081,28 +1102,28 @@ java_doublearray *builtin_newarray_double(s4 size)
    passed in an array of longs.
 
    Arguments:
-       n............number of dimensions to create
-       arrayvftbl...vftbl of the array class
-       dims.........array containing the size of each dimension to create
+       n.............number of dimensions to create
+       arrayclass....the array class
+       dims..........array containing the size of each dimension to create
 
    Return value: pointer to the array or NULL if no memory is
    available
 
 ******************************************************************************/
 
-static java_arrayheader *builtin_multianewarray_intern(int n,
-                                                                                                          classinfo *arrayclass,
-                                                                                                          long *dims)
+static java_handle_t *builtin_multianewarray_intern(int n,
+                                                                                                       classinfo *arrayclass,
+                                                                                                       long *dims)
 {
-       s4                size;
-       java_arrayheader *a;
-       classinfo        *componentclass;
-       s4                i;
+       s4             size;
+       java_handle_t *a;
+       classinfo     *componentclass;
+       s4             i;
 
        /* create this dimension */
 
        size = (s4) dims[0];
-       a = builtin_newarray(size, arrayclass);
+       a = builtin_newarray(size, arrayclass);
 
        if (!a)
                return NULL;
@@ -1121,7 +1142,7 @@ static java_arrayheader *builtin_multianewarray_intern(int n,
        /* create the component arrays */
 
        for (i = 0; i < size; i++) {
-               java_arrayheader *ea =
+               java_handle_t *ea =
 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
                        /* we save an s4 to a s8 slot, 8-byte aligned */
 
@@ -1132,8 +1153,8 @@ static java_arrayheader *builtin_multianewarray_intern(int n,
 
                if (!ea)
                        return NULL;
-               
-               ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
+
+               LLNI_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
        }
 
        return a;
@@ -1147,8 +1168,8 @@ static java_arrayheader *builtin_multianewarray_intern(int n,
 
 ******************************************************************************/
 
-java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
-                                                                                long *dims)
+java_handle_objectarray_t *builtin_multianewarray(int n, classinfo *arrayclass,
+                                                                                                 long *dims)
 {
        s4 i;
        s4 size;
@@ -1171,7 +1192,8 @@ java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
 
        /* now call the real function */
 
-       return builtin_multianewarray_intern(n, arrayclass, dims);
+       return (java_handle_objectarray_t *)
+               builtin_multianewarray_intern(n, arrayclass, dims);
 }
 
 
@@ -1183,144 +1205,6 @@ java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
        
 *****************************************************************************/
 
-#if !defined(NDEBUG)
-static s4 methodindent = 0;
-static u4 callcount = 0;
-
-java_objectheader *builtin_trace_exception(java_objectheader *xptr,
-                                                                                  methodinfo *m,
-                                                                                  void *pos,
-                                                                                  s4 indent)
-{
-       char *logtext;
-       s4    logtextlen;
-       s4    dumpsize;
-       codeinfo *code;
-
-       if (opt_verbosecall && indent)
-               methodindent--;
-
-       /* calculate message length */
-
-       if (xptr) {
-               logtextlen =
-                       strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
-       } 
-       else {
-               logtextlen = strlen("Some Throwable");
-       }
-
-       logtextlen += strlen(" thrown in ");
-
-       if (m) {
-               logtextlen +=
-                       utf_bytes(m->class->name) +
-                       strlen(".") +
-                       utf_bytes(m->name) +
-                       utf_bytes(m->descriptor) +
-                       strlen("(NOSYNC,NATIVE");
-
-#if SIZEOF_VOID_P == 8
-               logtextlen +=
-                       strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
-#else
-               logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
-#endif
-
-               if (m->class->sourcefile == NULL)
-                       logtextlen += strlen("<NO CLASSFILE INFORMATION>");
-               else
-                       logtextlen += utf_bytes(m->class->sourcefile);
-
-               logtextlen += strlen(":65536)");
-
-       } 
-       else {
-               logtextlen += strlen("call_java_method");
-       }
-
-       logtextlen += strlen("0");
-
-       /* allocate memory */
-
-       dumpsize = dump_size();
-
-       logtext = DMNEW(char, logtextlen);
-
-       if (xptr) {
-               strcpy(logtext, "Exception ");
-               utf_cat_classname(logtext, xptr->vftbl->class->name);
-
-       } else {
-               strcpy(logtext, "Some Throwable");
-       }
-
-       strcat(logtext, " thrown in ");
-
-       if (m) {
-               utf_cat_classname(logtext, m->class->name);
-               strcat(logtext, ".");
-               utf_cat(logtext, m->name);
-               utf_cat(logtext, m->descriptor);
-
-               if (m->flags & ACC_SYNCHRONIZED)
-                       strcat(logtext, "(SYNC");
-               else
-                       strcat(logtext, "(NOSYNC");
-
-               if (m->flags & ACC_NATIVE) {
-                       strcat(logtext, ",NATIVE");
-
-                       code = m->code;
-
-#if SIZEOF_VOID_P == 8
-                       sprintf(logtext + strlen(logtext),
-                                       ")(0x%016lx) at position 0x%016lx",
-                                       (ptrint) code->entrypoint, (ptrint) pos);
-#else
-                       sprintf(logtext + strlen(logtext),
-                                       ")(0x%08x) at position 0x%08x",
-                                       (ptrint) code->entrypoint, (ptrint) pos);
-#endif
-
-               } else {
-
-                       /* XXX preliminary: This should get the actual codeinfo */
-                       /* in which the exception happened.                     */
-                       code = m->code;
-                       
-#if SIZEOF_VOID_P == 8
-                       sprintf(logtext + strlen(logtext),
-                                       ")(0x%016lx) at position 0x%016lx (",
-                                       (ptrint) code->entrypoint, (ptrint) pos);
-#else
-                       sprintf(logtext + strlen(logtext),
-                                       ")(0x%08x) at position 0x%08x (",
-                                       (ptrint) code->entrypoint, (ptrint) pos);
-#endif
-
-                       if (m->class->sourcefile == NULL)
-                               strcat(logtext, "<NO CLASSFILE INFORMATION>");
-                       else
-                               utf_cat(logtext, m->class->sourcefile);
-
-                       sprintf(logtext + strlen(logtext), ":%d)", 0);
-               }
-
-       } else
-               strcat(logtext, "call_java_method");
-
-       log_text(logtext);
-
-       /* release memory */
-
-       dump_release(dumpsize);
-
-       return xptr;
-}
-#endif /* !defined(NDEBUG) */
-
-
 /* builtin_print_argument ******************************************************
 
    Prints arguments and return values for the call trace.
@@ -1332,8 +1216,7 @@ static char *builtin_print_argument(char *logtext, s4 *logtextlen,
                                                                        typedesc *paramtype, s8 value)
 {
        imm_union          imu;
-       java_objectheader *o;
-       java_lang_String  *s;
+       java_object_t     *o;
        classinfo         *c;
        utf               *u;
        u4                 len;
@@ -1354,7 +1237,12 @@ static char *builtin_print_argument(char *logtext, s4 *logtextlen,
                break;
 
        case TYPE_FLT:
+#if defined(__S390__)
+               imu.l = value;
+               /* The below won't work on S390 */
+#else
                imu.i = (s4) value;
+#endif
                sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
                break;
 
@@ -1376,7 +1264,7 @@ static char *builtin_print_argument(char *logtext, s4 *logtextlen,
 
                /* cast to java.lang.Object */
 
-               o = (java_objectheader *) (ptrint) value;
+               o = (java_object_t *) (ptrint) value;
 
                /* check return argument for java.lang.Class or java.lang.String */
 
@@ -1385,9 +1273,7 @@ static char *builtin_print_argument(char *logtext, s4 *logtextlen,
                                /* get java.lang.String object and the length of the
                                   string */
 
-                               s = (java_lang_String *) o;
-
-                               u = javastring_toutf(s, false);
+                               u = javastring_toutf(o, false);
 
                                len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
 
@@ -1439,8 +1325,7 @@ static char *builtin_print_argument(char *logtext, s4 *logtextlen,
 }
 #endif /* !defined(NDEBUG) */
 
-
-/* builtin_trace_args **********************************************************
+/* builtin_verbosecall_enter ***************************************************
 
    Print method call with arguments for -verbose:call.
 
@@ -1449,17 +1334,17 @@ static char *builtin_print_argument(char *logtext, s4 *logtextlen,
 #if !defined(NDEBUG)
 
 #ifdef TRACE_ARGS_NUM
-void builtin_trace_args(s8 a0, s8 a1,
-#if TRACE_ARGS_NUM >= 4
-                                               s8 a2, s8 a3,
-#endif /* TRACE_ARGS_NUM >= 4 */
-#if TRACE_ARGS_NUM >= 6
-                                               s8 a4, s8 a5,
-#endif /* TRACE_ARGS_NUM >= 6 */
-#if TRACE_ARGS_NUM == 8
-                                               s8 a6, s8 a7,
-#endif /* TRACE_ARGS_NUM == 8 */
-                                               methodinfo *m)
+void builtin_verbosecall_enter(s8 a0, s8 a1,
+# if TRACE_ARGS_NUM >= 4
+                                                          s8 a2, s8 a3,
+# endif
+# if TRACE_ARGS_NUM >= 6
+                                                          s8 a4, s8 a5,
+# endif
+# if TRACE_ARGS_NUM == 8
+                                                          s8 a6, s8 a7,
+# endif
+                                                          methodinfo *m)
 {
        methoddesc *md;
        char       *logtext;
@@ -1467,9 +1352,22 @@ void builtin_trace_args(s8 a0, s8 a1,
        s4          dumpsize;
        s4          i;
        s4          pos;
+       int         methodindent;
+       int         callcount;
+
+#if defined(ENABLE_DEBUG_FILTER)
+       if (! show_filters_test_verbosecall_enter(m)) return;
+#endif
+
+#if defined(ENABLE_VMLOG)
+       vmlog_cacao_enter_method(m);
+       return;
+#endif
 
        md = m->parseddesc;
 
+       methodindent = TRACEJAVACALLINDENT;
+
        /* calculate message length */
 
        logtextlen =
@@ -1480,13 +1378,12 @@ void builtin_trace_args(s8 a0, s8 a1,
                utf_bytes(m->class->name) +
                strlen(".") +
                utf_bytes(m->name) +
-               utf_bytes(m->descriptor) +
-               strlen("(") + strlen(")");
+               utf_bytes(m->descriptor);
 
        /* Actually it's not possible to have all flags printed, but:
           safety first! */
 
-       logtextlen =
+       logtextlen +=
                strlen(" PUBLIC") +
                strlen(" PRIVATE") +
                strlen(" PROTECTED") +
@@ -1502,8 +1399,10 @@ void builtin_trace_args(s8 a0, s8 a1,
        /* add maximal argument length */
 
        logtextlen +=
+               strlen("(") +
                strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
-               strlen("...(255)");
+               strlen("...(255)") +
+               strlen(")");
 
        /* allocate memory */
 
@@ -1511,7 +1410,7 @@ void builtin_trace_args(s8 a0, s8 a1,
 
        logtext = DMNEW(char, logtextlen);
 
-       callcount++;
+       callcount = ++TRACEJAVACALLCOUNT;
 
        sprintf(logtext, "%10d ", callcount);
        sprintf(logtext + strlen(logtext), "-%d-", methodindent);
@@ -1615,20 +1514,21 @@ void builtin_trace_args(s8 a0, s8 a1,
 
        dump_release(dumpsize);
 
-       methodindent++;
+       TRACEJAVACALLINDENT++;
+
 }
 #endif
 #endif /* !defined(NDEBUG) */
 
 
-/* builtin_displaymethodstop ***************************************************
+/* builtin_verbosecall_exit ****************************************************
 
    Print method exit for -verbose:call.
 
 *******************************************************************************/
 
 #if !defined(NDEBUG)
-void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
+void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
 {
        methoddesc *md;
        char       *logtext;
@@ -1637,9 +1537,28 @@ void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
        s4          i;
        s4          pos;
        imm_union   val;
+       int         methodindent;
+
+#if defined(ENABLE_DEBUG_FILTER)
+       if (! show_filters_test_verbosecall_exit(m)) return;
+#endif
+
+#if defined(ENABLE_VMLOG)
+       vmlog_cacao_leave_method(m);
+       return;
+#endif
 
        md = m->parseddesc;
 
+       /* outdent the log message */
+
+       if (TRACEJAVACALLINDENT)
+               TRACEJAVACALLINDENT--;
+       else
+               log_text("WARNING: unmatched methodindent--");
+
+       methodindent = TRACEJAVACALLINDENT;
+
        /* calculate message length */
 
        logtextlen =
@@ -1663,13 +1582,6 @@ void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
 
        logtext = DMNEW(char, logtextlen);
 
-       /* outdent the log message */
-
-       if (methodindent)
-               methodindent--;
-       else
-               log_text("WARNING: unmatched methodindent--");
-
        /* generate the message */
 
        sprintf(logtext, "           ");
@@ -1714,6 +1626,7 @@ void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
        /* release memory */
 
        dump_release(dumpsize);
+
 }
 #endif /* !defined(NDEBUG) */
 
@@ -1744,7 +1657,7 @@ void builtin_print_cycles_stats(FILE *file)
 
 ******************************************************************************/
 
-#if !SUPPORT_DIVISION
+#if !SUPPORT_DIVISION || defined(DISABLE_GC)
 s4 builtin_idiv(s4 a, s4 b)
 {
        s4 c;
@@ -1762,7 +1675,7 @@ s4 builtin_irem(s4 a, s4 b)
 
        return c;
 }
-#endif /* !SUPPORT_DIVISION */
+#endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
 
 
 /* functions for long arithmetics **********************************************
@@ -1830,7 +1743,7 @@ s8 builtin_lmul(s8 a, s8 b)
 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
 
 
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
 s8 builtin_ldiv(s8 a, s8 b)
 {
        s8 c;
@@ -2110,17 +2023,26 @@ float builtin_fneg(float a)
 #endif /* !SUPPORT_FLOAT */
 
 
-#if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
+#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
 s4 builtin_fcmpl(float a, float b)
 {
-       if (isnanf(a)) return -1;
-       if (isnanf(b)) return -1;
+       if (isnanf(a))
+               return -1;
+
+       if (isnanf(b))
+               return -1;
+
        if (!finitef(a) || !finitef(b)) {
                a = finitef(a) ? 0 : copysignf(1.0,     a);
                b = finitef(b) ? 0 : copysignf(1.0, b);
        }
-       if (a > b) return 1;
-       if (a == b) return 0;
+
+       if (a > b)
+               return 1;
+
+       if (a == b)
+               return 0;
+
        return -1;
 }
 
@@ -2137,7 +2059,7 @@ s4 builtin_fcmpg(float a, float b)
        if (a == b) return 0;
        return -1;
 }
-#endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
+#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
 
 
 float builtin_frem(float a, float b)
@@ -2289,34 +2211,52 @@ double builtin_dneg(double a)
 #endif /* !SUPPORT_DOUBLE */
 
 
-#if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
+#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
 s4 builtin_dcmpl(double a, double b)
 {
-       if (isnan(a)) return -1;
-       if (isnan(b)) return -1;
+       if (isnan(a))
+               return -1;
+
+       if (isnan(b))
+               return -1;
+
        if (!finite(a) || !finite(b)) {
                a = finite(a) ? 0 : copysign(1.0, a);
                b = finite(b) ? 0 : copysign(1.0, b);
        }
-       if (a > b) return 1;
-       if (a == b) return 0;
+
+       if (a > b)
+               return 1;
+
+       if (a == b)
+               return 0;
+
        return -1;
 }
 
 
 s4 builtin_dcmpg(double a, double b)
 {
-       if (isnan(a)) return 1;
-       if (isnan(b)) return 1;
+       if (isnan(a))
+               return 1;
+
+       if (isnan(b))
+               return 1;
+
        if (!finite(a) || !finite(b)) {
                a = finite(a) ? 0 : copysign(1.0, a);
                b = finite(b) ? 0 : copysign(1.0, b);
        }
-       if (a > b) return 1;
-       if (a == b) return 0;
+
+       if (a > b)
+               return 1;
+
+       if (a == b)
+               return 0;
+
        return -1;
 }
-#endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
+#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
 
 
 double builtin_drem(double a, double b)
@@ -2395,7 +2335,7 @@ double builtin_l2d(s8 a)
 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
 
 
-#if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
+#if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
 s4 builtin_f2i(float a) 
 {
        s4 i;
@@ -2420,10 +2360,10 @@ s4 builtin_f2i(float a)
                return 2147483647;
                return (-2147483648); */
 }
-#endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
+#endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
 
 
-#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
+#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
 s8 builtin_f2l(float a)
 {
        s8 l;
@@ -2451,7 +2391,7 @@ s8 builtin_f2l(float a)
 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
 
 
-#if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
+#if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
 s4 builtin_d2i(double a) 
 { 
        double d;
@@ -2470,10 +2410,10 @@ s4 builtin_d2i(double a)
                return 2147483647;
        return (-2147483647-1);
 }
-#endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
+#endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
 
 
-#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
+#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
 s8 builtin_d2l(double a)
 {
        double d;
@@ -2530,8 +2470,8 @@ float builtin_d2f(double a)
 
 *******************************************************************************/
 
-bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
-                                          java_arrayheader *dest, s4 destStart, s4 len)
+bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
+                                          java_handle_t *dest, s4 destStart, s4 len)
 {
        arraydescriptor *sdesc;
        arraydescriptor *ddesc;
@@ -2542,8 +2482,8 @@ bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
                return false;
        }
 
-       sdesc = src->objheader.vftbl->arraydesc;
-       ddesc = dest->objheader.vftbl->arraydesc;
+       sdesc = LLNI_vftbl_direct(src)->arraydesc;
+       ddesc = LLNI_vftbl_direct(dest)->arraydesc;
 
        if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
                exceptions_throw_arraystoreexception();
@@ -2553,8 +2493,8 @@ bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
        /* we try to throw exception with the same message as SUN does */
 
        if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
-               (srcStart  + len < 0) || (srcStart  + len > src->size) ||
-               (destStart + len < 0) || (destStart + len > dest->size)) {
+               (srcStart  + len < 0) || (srcStart  + len > LLNI_array_size(src)) ||
+               (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
                exceptions_throw_arrayindexoutofboundsexception();
                return false;
        }
@@ -2572,19 +2512,19 @@ bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
        else {
                /* We copy references of different type */
 
-               java_objectarray *oas = (java_objectarray *) src;
-               java_objectarray *oad = (java_objectarray *) dest;
-                
+               java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
+               java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
                if (destStart <= srcStart) {
                        for (i = 0; i < len; i++) {
-                               java_objectheader *o = oas->data[srcStart + i];
+                               java_handle_t *o;
+
+                               LLNI_objectarray_element_get(oas, srcStart + i, o);
 
-                               if (!builtin_canstore(oad, o)) {
-                                       exceptions_throw_arraystoreexception();
+                               if (!builtin_canstore(oad, o))
                                        return false;
-                               }
 
-                               oad->data[destStart + i] = o;
+                               LLNI_objectarray_element_set(oad, destStart + i, o);
                        }
                }
                else {
@@ -2595,14 +2535,14 @@ bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
                           index have been copied before the throw. */
 
                        for (i = len - 1; i >= 0; i--) {
-                               java_objectheader *o = oas->data[srcStart + i];
+                               java_handle_t *o;
 
-                               if (!builtin_canstore(oad, o)) {
-                                       exceptions_throw_arraystoreexception();
+                               LLNI_objectarray_element_get(oas, srcStart + i, o);
+
+                               if (!builtin_canstore(oad, o))
                                        return false;
-                               }
 
-                               oad->data[destStart + i] = o;
+                               LLNI_objectarray_element_set(oad, destStart + i, o);
                        }
                }
        }
@@ -2611,25 +2551,39 @@ bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
 }
 
 
-/* builtin_currenttimemillis ***************************************************
+/* builtin_nanotime ************************************************************
 
-   Return the current time in milliseconds.
+   Return the current time in nanoseconds.
 
 *******************************************************************************/
 
-s8 builtin_currenttimemillis(void)
+s8 builtin_nanotime(void)
 {
        struct timeval tv;
-       s8             result;
+       s8             usecs;
 
        if (gettimeofday(&tv, NULL) == -1)
                vm_abort("gettimeofday failed: %s", strerror(errno));
 
-       result = (s8) tv.tv_sec;
-       result *= 1000;
-       result += (tv.tv_usec / 1000);
+       usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
 
-       return result;
+       return usecs * 1000;
+}
+
+
+/* builtin_currenttimemillis ***************************************************
+
+   Return the current time in milliseconds.
+
+*******************************************************************************/
+
+s8 builtin_currenttimemillis(void)
+{
+       s8 msecs;
+
+       msecs = builtin_nanotime() / 1000 / 1000;
+
+       return msecs;
 }
 
 
@@ -2639,50 +2593,53 @@ s8 builtin_currenttimemillis(void)
 
 *******************************************************************************/
 
-java_objectheader *builtin_clone(void *env, java_objectheader *o)
+java_handle_t *builtin_clone(void *env, java_handle_t *o)
 {
-       arraydescriptor   *ad;
-       java_arrayheader  *ah;
-       u4                 size;
-       classinfo         *c;
-       java_objectheader *co;              /* cloned object header               */
+       arraydescriptor *ad;
+       java_handle_t   *ah;
+       u4               size;
+       classinfo       *c;
+       java_handle_t   *co;                /* cloned object header               */
 
        /* get the array descriptor */
 
-       ad = o->vftbl->arraydesc;
+       ad = LLNI_vftbl_direct(o)->arraydesc;
 
        /* we are cloning an array */
 
        if (ad != NULL) {
-               ah = (java_arrayheader *) o;
+               ah = (java_handle_t *) o;
 
-               size = ad->dataoffset + ad->componentsize * ah->size;
+               size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
         
-               co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
+               co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
 
                if (co == NULL)
                        return NULL;
 
                MCOPY(co, o, u1, size);
 
+#if defined(ENABLE_GC_CACAO)
+               heap_init_objectheader(co, size);
+#endif
+
 #if defined(ENABLE_THREADS)
                lock_init_object_lock(co);
 #endif
-        
+
                return co;
        }
     
     /* we are cloning a non-array */
 
     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
-        *exceptionptr =
-                       new_exception(string_java_lang_CloneNotSupportedException);
+        exceptions_throw_clonenotsupportedexception();
         return NULL;
     }
 
        /* get the class of the object */
 
-    c = o->vftbl->class;
+       LLNI_class_get(o, c);
 
        /* create new object */
 
@@ -2693,6 +2650,10 @@ java_objectheader *builtin_clone(void *env, java_objectheader *o)
 
     MCOPY(co, o, u1, c->instancesize);
 
+#if defined(ENABLE_GC_CACAO)
+       heap_init_objectheader(co, c->instancesize);
+#endif
+
 #if defined(ENABLE_THREADS)
        lock_init_object_lock(co);
 #endif
@@ -2700,6 +2661,11 @@ java_objectheader *builtin_clone(void *env, java_objectheader *o)
     return co;
 }
 
+#if defined(ENABLE_VMLOG)
+#define NDEBUG
+#include <vmlog_cacao.c>
+#endif
+
 
 /*
  * These are local overrides for various environment variables in Emacs.