minor documentation corrections
[cacao.git] / builtin.c
index bd1e4e2d46ac77fa5db809a763d25d2fe7eb6cd0..bf2511e041d9ae1cbd824c048e974f80a5774dc0 100644 (file)
--- a/builtin.c
+++ b/builtin.c
    calls instead of machine instructions, using the C calling
    convention.
 
-   $Id: builtin.c 685 2003-12-04 01:25:54Z jowenn $
+   $Id: builtin.c 890 2004-01-19 12:24:13Z edwin $
 
 */
 
 
 #include <assert.h>
 #include <string.h>
+#include <math.h>
 #include "main.h"
 #include "global.h"
 #include "builtin.h"
 #include "loader.h"
 #include "tables.h"
 #include "asmpart.h"
+#include "mm/boehm.h"
 #include "threads/thread.h"
 #include "threads/locks.h"
 #include "toolbox/loging.h"
 #include "toolbox/memory.h"
+#include "nat/java_lang_Cloneable.h"
+#include "nat/java_lang_VMObject.h"
 
-#include "native-math.h"
 
 #undef DEBUG /*define DEBUG 1*/
 
-builtin_descriptor builtin_desc[] = {
-       {(functionptr) builtin_instanceof,                 "instanceof"},
-       {(functionptr) builtin_checkcast,                  "checkcast"},
-       {(functionptr) asm_builtin_checkcast,      "checkcast"},
-       {(functionptr) builtin_arrayinstanceof,    "arrayinstanceof"},
-#if defined(__I386__)
-       {(functionptr) asm_builtin_arrayinstanceof,"arrayinstanceof"},
-#endif
-       {(functionptr) builtin_checkarraycast,     "checkarraycast"},
-       {(functionptr) asm_builtin_checkarraycast, "checkarraycast"},
-       {(functionptr) asm_builtin_aastore,                "aastore"},
-       {(functionptr) builtin_new,                                "new"},
-       {(functionptr) builtin_newarray,       "newarray"},
-       {(functionptr) builtin_anewarray,          "anewarray"},
-#if defined(__I386__)
-       /*
-        * have 2 parameters (needs stack manipulation)
-        */
-       {(functionptr) asm_builtin_newarray,       "newarray"},
-#endif
-       {(functionptr) builtin_newarray_boolean,   "newarray_boolean"},
-       {(functionptr) builtin_newarray_char,      "newarray_char"},
-       {(functionptr) builtin_newarray_float,     "newarray_float"},
-       {(functionptr) builtin_newarray_double,    "newarray_double"},
-       {(functionptr) builtin_newarray_byte,      "newarray_byte"},
-       {(functionptr) builtin_newarray_short,     "newarray_short"},
-       {(functionptr) builtin_newarray_int,       "newarray_int"},
-       {(functionptr) builtin_newarray_long,      "newarray_long"},
-       {(functionptr) builtin_displaymethodstart, "displaymethodstart"},
-       {(functionptr) builtin_displaymethodstop,  "displaymethodstop"},
-       {(functionptr) builtin_monitorenter,       "monitorenter"},
-       {(functionptr) asm_builtin_monitorenter,   "monitorenter"},
-       {(functionptr) builtin_monitorexit,                "monitorexit"},
-       {(functionptr) asm_builtin_monitorexit,    "monitorexit"},
-#if !SUPPORT_DIVISION
-       {(functionptr) builtin_idiv,                       "idiv"},
-       {(functionptr) asm_builtin_idiv,                   "idiv"},
-       {(functionptr) builtin_irem,                       "irem"},
-       {(functionptr) asm_builtin_irem,                   "irem"},
-#endif
-       {(functionptr) builtin_ladd,                       "ladd"},
-       {(functionptr) builtin_lsub,                       "lsub"},
-       {(functionptr) builtin_lmul,                       "lmul"},
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
-       {(functionptr) builtin_ldiv,                       "ldiv"},
-       {(functionptr) asm_builtin_ldiv,                   "ldiv"},
-       {(functionptr) builtin_lrem,                       "lrem"},
-       {(functionptr) asm_builtin_lrem,                   "lrem"},
-#endif
-       {(functionptr) builtin_lshl,                       "lshl"},
-       {(functionptr) builtin_lshr,                       "lshr"},
-       {(functionptr) builtin_lushr,                      "lushr"},
-       {(functionptr) builtin_land,                       "land"},
-       {(functionptr) builtin_lor,                                "lor"},
-       {(functionptr) builtin_lxor,                       "lxor"},
-       {(functionptr) builtin_lneg,                       "lneg"},
-       {(functionptr) builtin_lcmp,                       "lcmp"},
-       {(functionptr) builtin_fadd,                       "fadd"},
-       {(functionptr) builtin_fsub,                       "fsub"},
-       {(functionptr) builtin_fmul,                       "fmul"},
-       {(functionptr) builtin_fdiv,                       "fdiv"},
-       {(functionptr) builtin_frem,                       "frem"},
-       {(functionptr) builtin_fneg,                       "fneg"},
-       {(functionptr) builtin_fcmpl,                      "fcmpl"},
-       {(functionptr) builtin_fcmpg,                      "fcmpg"},
-       {(functionptr) builtin_dadd,                       "dadd"},
-       {(functionptr) builtin_dsub,                       "dsub"},
-       {(functionptr) builtin_dmul,                       "dmul"},
-       {(functionptr) builtin_ddiv,                       "ddiv"},
-       {(functionptr) builtin_drem,                       "drem"},
-       {(functionptr) builtin_dneg,                       "dneg"},
-       {(functionptr) builtin_dcmpl,                      "dcmpl"},
-       {(functionptr) builtin_dcmpg,                      "dcmpg"},
-       {(functionptr) builtin_i2l,                                "i2l"},
-       {(functionptr) builtin_i2f,                                "i2f"},
-       {(functionptr) builtin_i2d,                                "i2d"},
-       {(functionptr) builtin_l2i,                                "l2i"},
-       {(functionptr) builtin_l2f,                                "l2f"},
-       {(functionptr) builtin_l2d,                                "l2d"},
-       {(functionptr) builtin_f2i,                                "f2i"},
-       {(functionptr) builtin_f2l,                                "f2l"},
-       {(functionptr) builtin_f2d,                                "f2d"},
-       {(functionptr) builtin_d2i,                                "d2i"},
-       {(functionptr) builtin_d2l,                                "d2l"},
-#if defined(__I386__)
-       {(functionptr) asm_builtin_f2i,                    "f2i"},
-       {(functionptr) asm_builtin_f2l,                    "f2l"},
-       {(functionptr) asm_builtin_d2i,                    "d2i"},
-       {(functionptr) asm_builtin_d2l,                    "d2l"},
-#endif
-       {(functionptr) builtin_d2f,                                "d2f"},
-       {(functionptr) NULL,                                       "unknown"}
-};
-
 
 /*****************************************************************************
                                                                TYPE CHECKS
@@ -166,10 +75,11 @@ builtin_descriptor builtin_desc[] = {
                                   0 ... otherwise
                                        
 *****************************************************************************/                                 
-
-s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
+s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
 { 
-       classinfo *tmp;
+       s4 res;
+
+       /*classinfo *tmp;*/
        if (super->flags & ACC_INTERFACE)
                return (sub->vftbl->interfacetablelength > super->index) &&
                        (sub->vftbl->interfacetable[-super->index] != NULL);
@@ -202,21 +112,42 @@ s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
                        sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
                        super->vftbl->diffval); */
 
-       return (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cast_lock();
+#endif
+
+       res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
                (unsigned) (super->vftbl->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cast_unlock();
+#endif
+
+       return res;
 }
 
-/* XXX inline this? */
 s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
 {
        int base;
+       s4 res;
        
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cast_lock();
+#endif
+
        if ((base = super->baseval) <= 0)
                /* super is an interface */
-               return (sub->interfacetablelength > -base) &&
+               res = (sub->interfacetablelength > -base) &&
                        (sub->interfacetable[base] != NULL);
-       return (unsigned) (sub->baseval - base)
-               <= (unsigned) (super->diffval);
+       else
+           res = (unsigned) (sub->baseval - base)
+                       <= (unsigned) (super->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cast_unlock();
+#endif
+
+       return res;
 }
 
 
@@ -281,7 +212,6 @@ s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
                        
 ******************************************************************************/
 
-/* XXX inline this? */
 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
 {
        if (desc==target) return 1;
@@ -297,6 +227,7 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *t
        return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
 }
 
+
 /******************** function: builtin_checkarraycast ***********************
 
        Checks if an object is really a subtype of the requested array type.
@@ -314,22 +245,24 @@ static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *t
                        
 *****************************************************************************/
 
-s4 builtin_checkarraycast(java_objectheader *o,arraydescriptor *target)
+s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
 {
        arraydescriptor *desc;
        
        if (!o) return 1;
        if ((desc = o->vftbl->arraydesc) == NULL) return 0;
 
-       return builtin_descriptorscompatible(desc,target);
+       return builtin_descriptorscompatible(desc, target->arraydesc);
 }
 
-s4 builtin_arrayinstanceof(java_objectheader *obj,arraydescriptor *desc)
+
+s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
 {
        if (!obj) return 1;
-       return builtin_checkarraycast (obj, desc);
+       return builtin_checkarraycast(obj, target);
 }
 
+
 /************************** exception functions *******************************
 
 ******************************************************************************/
@@ -337,6 +270,7 @@ s4 builtin_arrayinstanceof(java_objectheader *obj,arraydescriptor *desc)
 java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
 {
        if (verbose) {
+               char logtext[MAXLOGTEXT];
                sprintf(logtext, "Builtin exception thrown: ");
                if (local_exceptionptr)
                        utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
@@ -353,12 +287,25 @@ java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr
                        if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
                        if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
                        }
-               dolog();
+               log_text(logtext);
        }
-       exceptionptr = local_exceptionptr;
+       *exceptionptr = local_exceptionptr;
        return local_exceptionptr;
 }
 
+void builtin_reset_exceptionptr()
+{
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#ifdef HAVE___THREAD
+       _exceptionptr = NULL;
+#else
+       ((nativethread*) pthread_getspecific(tkey_exceptionptr))->_exceptionptr = 0;
+#endif
+#else
+       panic("builtin_reset_exceptionptr should not be used in this configuration");
+#endif
+}
+
 
 /******************* function: builtin_canstore *******************************
 
@@ -391,6 +338,8 @@ s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
        valuevftbl = o->vftbl;
 
     if ((dim_m1 = desc->dimension - 1) == 0) {
+               s4 res;
+
                /* {a is a one-dimensional array} */
                /* {a is an array of references} */
                
@@ -402,8 +351,18 @@ s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
                        return (valuevftbl->interfacetablelength > -base &&
                                        valuevftbl->interfacetable[base] != NULL);
                
-               return (unsigned)(valuevftbl->baseval - base)
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+               cast_lock();
+#endif
+
+               res = (unsigned)(valuevftbl->baseval - base)
                        <= (unsigned)(componentvftbl->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+               cast_unlock();
+#endif
+
+               return res;
     }
     /* {a has dimension > 1} */
        /* {componentvftbl->arraydesc != NULL} */
@@ -416,6 +375,7 @@ s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
        return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
 }
 
+
 /* This is an optimized version where a is guaranteed to be one-dimensional */
 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
 {
@@ -423,6 +383,7 @@ s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
        vftbl *elementvftbl;
        vftbl *valuevftbl;
        int base;
+       s4 res;
        
        if (!o) return 1;
 
@@ -448,17 +409,28 @@ s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
                return (valuevftbl->interfacetablelength > -base &&
                                valuevftbl->interfacetable[base] != NULL);
        
-       return (unsigned)(valuevftbl->baseval - base)
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cast_lock();
+#endif
+
+       res = (unsigned)(valuevftbl->baseval - base)
                <= (unsigned)(elementvftbl->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cast_unlock();
+#endif
+
+       return res;
 }
 
+
 /* This is an optimized version where a is guaranteed to be a
  * one-dimensional array of a class type */
-/* XXX this could be inlined by the code generator */
-s4 builtin_canstore_onedim_class (java_objectarray *a, java_objectheader *o)
+s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
 {
        vftbl *elementvftbl;
        vftbl *valuevftbl;
+       s4 res;
        
        if (!o) return 1;
 
@@ -479,8 +451,18 @@ s4 builtin_canstore_onedim_class (java_objectarray *a, java_objectheader *o)
        if (valuevftbl == elementvftbl)
                return 1;
 
-       return (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cast_lock();
+#endif
+
+       res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
                <= (unsigned)(elementvftbl->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       cast_unlock();
+#endif
+
+       return res;
 }
 
 
@@ -499,6 +481,13 @@ java_objectheader *builtin_new(classinfo *c)
 {
        java_objectheader *o;
 
+       if (initverbose) {
+               char logtext[MAXLOGTEXT];
+               sprintf(logtext, "Initialize class ");
+               utf_sprint(logtext + strlen(logtext), c->name);
+               sprintf(logtext + strlen(logtext), " (from builtin_new)");
+               log_text(logtext);
+       }
        class_init(c);
 
 #ifdef SIZE_FROM_CLASSINFO
@@ -527,41 +516,48 @@ java_objectheader *builtin_new(classinfo *c)
 
 *****************************************************************************/
 
-java_arrayheader *builtin_newarray(s4 size,vftbl *arrayvftbl)
+java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
 {
-        java_arrayheader *a;
-        arraydescriptor *desc = arrayvftbl->arraydesc;
-        s4 dataoffset = desc->dataoffset;
-        s4 componentsize = desc->componentsize;
+       java_arrayheader *a;
+       arraydescriptor *desc = arrayvftbl->arraydesc;
+       s4 dataoffset = desc->dataoffset;
+       s4 componentsize = desc->componentsize;
+       s4 actualsize;
 
        if (size<0) {
-               exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
+               *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
                return NULL;
        }
 #ifdef SIZE_FROM_CLASSINFO
-        s4 actualsize = align_size(dataoffset + size * componentsize);
+       actualsize = align_size(dataoffset + size * componentsize);
 #else
-        s4 actualsize = dataoffset + size * componentsize;
+       actualsize = dataoffset + size * componentsize;
 #endif
-        a = (java_arrayheader *)
-                heap_allocate(actualsize,
-                                          (desc->arraytype == ARRAYTYPE_OBJECT),
-                                          NULL);
 
-        if (!a) return NULL;
-        memset(a,0,actualsize);
+       if (((u4)actualsize)<((u4)size)) { /* overflow */
+               *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
+               return NULL;
+       }
+       a = heap_allocate(actualsize,
+                                         (desc->arraytype == ARRAYTYPE_OBJECT),
+                                         NULL);
+
+       if (!a) return NULL;
+       memset(a, 0, actualsize);
 
 
        /*printf("builtin_newarray: Created an array of size : %d\n",size);*/
 
-        a->objheader.vftbl = arrayvftbl;
-        a->size = size;
+       a->objheader.vftbl = arrayvftbl;
+       a->size = size;
 #ifdef SIZE_FROM_CLASSINFO
-        a->alignedsize = actualsize;
+       a->alignedsize = actualsize;
 #endif
-        return a;
+
+       return a;
 }
 
+
 /********************** Function: builtin_anewarray *************************
 
        Creates an array of references to the given class type on the heap.
@@ -574,12 +570,12 @@ java_arrayheader *builtin_newarray(s4 size,vftbl *arrayvftbl)
 
 *****************************************************************************/
 
-java_objectarray *
-builtin_anewarray(s4 size,classinfo *component)
+java_objectarray *builtin_anewarray(s4 size, classinfo *component)
 {
-       return (java_objectarray*) builtin_newarray(size,class_array_of(component)->vftbl);
+       return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
 }
 
+
 /******************** Function: builtin_newarray_int ***********************
 
        Creates an array of 32 bit Integers on the heap.
@@ -588,11 +584,12 @@ builtin_anewarray(s4 size,classinfo *component)
 
 *****************************************************************************/
 
-java_intarray *builtin_newarray_int (s4 size)
+java_intarray *builtin_newarray_int(s4 size)
 {
-       return (java_intarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
+       return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
 }
 
+
 /******************** Function: builtin_newarray_long ***********************
 
        Creates an array of 64 bit Integers on the heap.
@@ -601,11 +598,12 @@ java_intarray *builtin_newarray_int (s4 size)
 
 *****************************************************************************/
 
-java_longarray *builtin_newarray_long (s4 size)
+java_longarray *builtin_newarray_long(s4 size)
 {
-       return (java_longarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
+       return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
 }
 
+
 /******************** function: builtin_newarray_float ***********************
 
        Creates an array of 32 bit IEEE floats on the heap.
@@ -614,11 +612,12 @@ java_longarray *builtin_newarray_long (s4 size)
 
 *****************************************************************************/
 
-java_floatarray *builtin_newarray_float (s4 size)
+java_floatarray *builtin_newarray_float(s4 size)
 {
-       return (java_floatarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
+       return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
 }
 
+
 /******************** function: builtin_newarray_double ***********************
 
        Creates an array of 64 bit IEEE floats on the heap.
@@ -627,11 +626,12 @@ java_floatarray *builtin_newarray_float (s4 size)
 
 *****************************************************************************/
 
-java_doublearray *builtin_newarray_double (s4 size)
+java_doublearray *builtin_newarray_double(s4 size)
 {
-       return (java_doublearray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
+       return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
 }
 
+
 /******************** function: builtin_newarray_byte ***********************
 
        Creates an array of 8 bit Integers on the heap.
@@ -640,11 +640,12 @@ java_doublearray *builtin_newarray_double (s4 size)
 
 *****************************************************************************/
 
-java_bytearray *builtin_newarray_byte (s4 size)
+java_bytearray *builtin_newarray_byte(s4 size)
 {
-       return (java_bytearray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
+       return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
 }
 
+
 /******************** function: builtin_newarray_char ************************
 
        Creates an array of characters on the heap.
@@ -653,11 +654,12 @@ java_bytearray *builtin_newarray_byte (s4 size)
 
 *****************************************************************************/
 
-java_chararray *builtin_newarray_char (s4 size)
+java_chararray *builtin_newarray_char(s4 size)
 {
-       return (java_chararray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
+       return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
 }
 
+
 /******************** function: builtin_newarray_short ***********************
 
        Creates an array of 16 bit Integers on the heap.
@@ -666,11 +668,12 @@ java_chararray *builtin_newarray_char (s4 size)
 
 *****************************************************************************/
 
-java_shortarray *builtin_newarray_short (s4 size)
+java_shortarray *builtin_newarray_short(s4 size)
 {
-       return (java_shortarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
+       return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
 }
 
+
 /******************** function: builtin_newarray_boolean ************************
 
        Creates an array of bytes on the heap. The array is designated as an array
@@ -680,11 +683,12 @@ java_shortarray *builtin_newarray_short (s4 size)
 
 *****************************************************************************/
 
-java_booleanarray *builtin_newarray_boolean (s4 size)
+java_booleanarray *builtin_newarray_boolean(s4 size)
 {
-       return (java_booleanarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
+       return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
 }
 
+
 /**************** function: builtin_nmultianewarray ***************************
 
        Creates a multi-dimensional array on the heap. The dimensions are passed in
@@ -699,8 +703,9 @@ java_booleanarray *builtin_newarray_boolean (s4 size)
 
 ******************************************************************************/
 
-java_arrayheader *builtin_nmultianewarray (int n,
-                                                                                  vftbl *arrayvftbl, long *dims)
+       /* Helper functions */
+
+java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
 {
        int size, i;
        java_arrayheader *a;
@@ -716,8 +721,10 @@ java_arrayheader *builtin_nmultianewarray (int n,
 
        /* get the vftbl of the components to create */
        componentvftbl = arrayvftbl->arraydesc->componentvftbl;
-       if (!componentvftbl) /* XXX the verifier could check this */
-               panic ("multianewarray with too many dimensions");
+
+       /* The verifier guarantees this. */
+       /* if (!componentvftbl) */
+       /*      panic ("multianewarray with too many dimensions"); */
 
        /* create the component arrays */
        for (i = 0; i < size; i++) {
@@ -730,6 +737,7 @@ java_arrayheader *builtin_nmultianewarray (int n,
        return a;
 }
 
+
 /*****************************************************************************
                                          METHOD LOGGING
 
@@ -741,17 +749,20 @@ java_arrayheader *builtin_nmultianewarray (int n,
 
 u4 methodindent = 0;
 
-java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
+java_objectheader *builtin_trace_exception(java_objectheader *_exceptionptr,
                                                                                   methodinfo *method, int *pos, 
                                                                                   int noindent)
 {
-
-       if (!noindent)
-               methodindent--;
+       if (!noindent) {
+               if (methodindent)
+                       methodindent--;
+               else
+                       log_text("WARNING: unmatched methodindent--");
+       }
        if (verbose || runverbose) {
                printf("Exception ");
-               if (exceptionptr) {
-                       utf_display (exceptionptr->vftbl->class->name);
+               if (_exceptionptr) {
+                       utf_display (_exceptionptr->vftbl->class->name);
                }
                else {
                        printf("Error: <Nullpointer instead of exception>");
@@ -782,7 +793,7 @@ java_objectheader *builtin_trace_exception(java_objectheader *exceptionptr,
                        printf("call_java_method\n");
                fflush (stdout);
        }
-       return exceptionptr;
+       return _exceptionptr;
 }
 
 
@@ -793,8 +804,8 @@ void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
 #endif
                                                methodinfo *method)
 {
-
        int i;
+       char logtext[MAXLOGTEXT];
        for (i = 0; i < methodindent; i++)
                logtext[i] = '\t';
        sprintf(logtext + methodindent, "called: ");
@@ -909,7 +920,7 @@ void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
 #endif
        }
        sprintf (logtext+strlen(logtext), ")");
-       dolog ();
+       log_text(logtext);
 
        methodindent++;
 }
@@ -918,13 +929,14 @@ void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3, s8 a4, s8 a5,
 
 void builtin_displaymethodstart(methodinfo *method)
 {
+       char logtext[MAXLOGTEXT];
        sprintf(logtext, "                                                                                              ");
        sprintf(logtext + methodindent, "called: ");
        utf_sprint(logtext + strlen(logtext), method->class->name);
        sprintf(logtext + strlen(logtext), ".");
        utf_sprint(logtext + strlen(logtext), method->name);
        utf_sprint(logtext + strlen(logtext), method->descriptor);
-       dolog();
+       log_text(logtext);
        methodindent++;
 }
 
@@ -932,9 +944,13 @@ void builtin_displaymethodstart(methodinfo *method)
 void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
 {
        int i;
+       char logtext[MAXLOGTEXT];
        for (i = 0; i < methodindent; i++)
                logtext[i] = '\t';
-       methodindent--;
+       if (methodindent)
+               methodindent--;
+       else
+               log_text("WARNING: unmatched methodindent--");
        sprintf(logtext + methodindent, "finished: ");
        utf_sprint(logtext + strlen(logtext), method->class->name);
        sprintf(logtext + strlen(logtext), ".");
@@ -966,13 +982,14 @@ void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
                sprintf(logtext + strlen(logtext), "->%g", d);
                break;
        }
-       dolog();
+       log_text(logtext);
 }
 
 
 void builtin_displaymethodexception(methodinfo *method)
 {
        int i;
+       char logtext[MAXLOGTEXT];
        for (i = 0; i < methodindent; i++)
                logtext[i] = '\t';
        sprintf(logtext + methodindent, "exception abort: ");
@@ -980,7 +997,7 @@ void builtin_displaymethodexception(methodinfo *method)
        sprintf(logtext + strlen(logtext), ".");
        utf_sprint(logtext + strlen(logtext), method->name);
        utf_sprint(logtext + strlen(logtext), method->descriptor);
-       dolog();
+       log_text(logtext);
 }
 
 
@@ -991,10 +1008,9 @@ void builtin_displaymethodexception(methodinfo *method)
 /*
  * Lock the mutex of an object.
  */
-#ifdef USE_THREADS
-void
-internal_lock_mutex_for_object (java_objectheader *object)
+void internal_lock_mutex_for_object(java_objectheader *object)
 {
+#ifdef USE_THREADS
        mutexHashEntry *entry;
        int hashValue;
 
@@ -1035,17 +1051,16 @@ internal_lock_mutex_for_object (java_objectheader *object)
                entry->object = object;
        
        internal_lock_mutex(&entry->mutex);
-}
 #endif
+}
 
 
 /*
  * Unlocks the mutex of an object.
  */
-#ifdef USE_THREADS
-void
-internal_unlock_mutex_for_object (java_objectheader *object)
+void internal_unlock_mutex_for_object (java_objectheader *object)
 {
+#ifdef USE_THREADS
        int hashValue;
        mutexHashEntry *entry;
 
@@ -1071,8 +1086,8 @@ internal_unlock_mutex_for_object (java_objectheader *object)
                        firstFreeOverflowEntry = unlinked;
                }
        }
-}
 #endif
+}
 
 
 void builtin_monitorenter(java_objectheader *o)
@@ -1277,8 +1292,8 @@ s4 builtin_lcmp(s8 a, s8 b)
 
 float builtin_fadd(float a, float b)
 {
-       if (isnanf(a)) return FLT_NAN;
-       if (isnanf(b)) return FLT_NAN;
+       if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+       if (isnanf(b)) return intBitsToFloat(FLT_NAN);
        if (finitef(a)) {
                if (finitef(b))
                        return a + b;
@@ -1292,7 +1307,7 @@ float builtin_fadd(float a, float b)
                        if (copysignf(1.0, a) == copysignf(1.0, b))
                                return a;
                        else
-                               return FLT_NAN;
+                               return intBitsToFloat(FLT_NAN);
                }
        }
 }
@@ -1306,18 +1321,18 @@ float builtin_fsub(float a, float b)
 
 float builtin_fmul(float a, float b)
 {
-       if (isnanf(a)) return FLT_NAN;
-       if (isnanf(b)) return FLT_NAN;
+       if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+       if (isnanf(b)) return intBitsToFloat(FLT_NAN);
        if (finitef(a)) {
-               if (finitef(b)) return a*b;
+               if (finitef(b)) return a * b;
                else {
-                       if (a == 0) return FLT_NAN;
+                       if (a == 0) return intBitsToFloat(FLT_NAN);
                        else return copysignf(b, copysignf(1.0, b)*a);
                }
        }
        else {
                if (finitef(b)) {
-                       if (b == 0) return FLT_NAN;
+                       if (b == 0) return intBitsToFloat(FLT_NAN);
                        else return copysignf(a, copysignf(1.0, a)*b);
                }
                else {
@@ -1334,12 +1349,12 @@ float builtin_fdiv(float a, float b)
                        return a / b;
                else {
                        if (a > 0)
-                               return FLT_POSINF;
+                               return intBitsToFloat(FLT_POSINF);
                        else if (a < 0)
-                               return FLT_NEGINF;
+                               return intBitsToFloat(FLT_NEGINF);
                }
        }
-       return FLT_NAN;
+       return intBitsToFloat(FLT_NAN);
 }
 
 
@@ -1392,17 +1407,17 @@ s4 builtin_fcmpg(float a, float b)
 
 double builtin_dadd(double a, double b)
 {
-       if (isnan(a)) return DBL_NAN;
-       if (isnan(b)) return DBL_NAN;
+       if (isnan(a)) return longBitsToDouble(DBL_NAN);
+       if (isnan(b)) return longBitsToDouble(DBL_NAN);
        if (finite(a)) {
-               if (finite(b)) return a+b;
+               if (finite(b)) return a + b;
                else return b;
        }
        else {
                if (finite(b)) return a;
                else {
                        if (copysign(1.0, a)==copysign(1.0, b)) return a;
-                       else return DBL_NAN;
+                       else return longBitsToDouble(DBL_NAN);
                }
        }
 }
@@ -1416,18 +1431,18 @@ double builtin_dsub(double a, double b)
 
 double builtin_dmul(double a, double b)
 {
-       if (isnan(a)) return DBL_NAN;
-       if (isnan(b)) return DBL_NAN;
+       if (isnan(a)) return longBitsToDouble(DBL_NAN);
+       if (isnan(b)) return longBitsToDouble(DBL_NAN);
        if (finite(a)) {
                if (finite(b)) return a * b;
                else {
-                       if (a == 0) return DBL_NAN;
+                       if (a == 0) return longBitsToDouble(DBL_NAN);
                        else return copysign(b, copysign(1.0, b) * a);
                }
        }
        else {
                if (finite(b)) {
-                       if (b == 0) return DBL_NAN;
+                       if (b == 0) return longBitsToDouble(DBL_NAN);
                        else return copysign(a, copysign(1.0, a) * b);
                }
                else {
@@ -1439,17 +1454,41 @@ double builtin_dmul(double a, double b)
 
 double builtin_ddiv(double a, double b)
 {
-       if (finite(a) && finite(b)) {
-               if (b != 0)
+       if (finite(a)) {
+               if (finite(b)) {
                        return a / b;
-               else {
+
+               } else {
+                       if (isnan(b))
+                               return longBitsToDouble(DBL_NAN);
+                       else
+                               return copysign(0.0, b);
+               }
+
+       } else {
+               if (finite(b)) {
                        if (a > 0)
-                               return DBL_POSINF;
+                               return longBitsToDouble(DBL_POSINF);
                        else if (a < 0)
-                               return DBL_NEGINF;
-               }
+                               return longBitsToDouble(DBL_NEGINF);
+
+               } else
+                       return longBitsToDouble(DBL_NAN);
        }
-       return DBL_NAN;
+
+/*     if (finite(a) && finite(b)) { */
+/*             if (b != 0) */
+/*                     return a / b; */
+/*             else { */
+/*                     if (a > 0) */
+/*                             return longBitsToDouble(DBL_POSINF); */
+/*                     else if (a < 0) */
+/*                             return longBitsToDouble(DBL_NEGINF); */
+/*             } */
+/*     } */
+
+       /* keep compiler happy */
+       return 0;
 }
 
 
@@ -1504,7 +1543,10 @@ s8 builtin_i2l(s4 i)
 #if U8_AVAILABLE
        return i;
 #else
-       s8 v; v.high = 0; v.low=i; return v;
+       s8 v;
+       v.high = 0;
+       v.low = i;
+       return v;
 #endif
 }
 
@@ -1606,9 +1648,9 @@ double builtin_f2d(float a)
        if (finitef(a)) return (double) a;
        else {
                if (isnanf(a))
-                       return DBL_NAN;
+                       return longBitsToDouble(DBL_NAN);
                else
-                       return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
+                       return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
        }
 }
 
@@ -1659,15 +1701,44 @@ float builtin_d2f(double a)
                return (float) a;
        else {
                if (isnan(a))
-                       return FLT_NAN;
+                       return intBitsToFloat(FLT_NAN);
                else
-                       return copysignf(FLT_POSINF, (float) copysign(1.0, a));
+                       return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
        }
 }
 
 
-java_arrayheader *builtin_clone_array(void *env,java_arrayheader *o) {
-        return Java_java_lang_VMObject_clone ( 0 ,  0, o);
+/* used to convert FLT_xxx defines into float values */
+
+inline float intBitsToFloat(s4 i)
+{
+       imm_union imb;
+
+       imb.i = i;
+       return imb.f;
+}
+
+
+/* used to convert DBL_xxx defines into double values */
+
+inline float longBitsToDouble(s8 l)
+{
+       imm_union imb;
+
+       imb.l = l;
+       return imb.d;
+}
+
+
+java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
+{
+       return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
+}
+
+s4 builtin_dummy()
+{
+       panic("Internal error: builtin_dummy called (native function is missing)");
+       return 0; /* for the compiler */
 }