* src/vm/global.h: Made 'lockword' member of java_object_t a plain
[cacao.git] / src / vm / jit / builtin.cpp
index 1b9ccb99c0eb23d4fc18d6df2d62d6d88b848c41..146e64dffdb87a8fbbc3820076088d0d08cb02ab 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/builtin.cpp - functions for unsupported operations
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2010
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -48,7 +48,7 @@
 #endif
 
 #include "mm/gc.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #include "native/llni.h"
 
@@ -56,7 +56,7 @@
 #include "threads/mutex.hpp"
 #include "threads/thread.hpp"
 
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
 #include "toolbox/util.h"
 
 #include "vm/array.hpp"
@@ -67,7 +67,7 @@
 #include "vm/global.h"
 #include "vm/globals.hpp"
 #include "vm/initialize.hpp"
-#include "vm/linker.h"
+#include "vm/linker.hpp"
 #include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
@@ -75,6 +75,7 @@
 #include "vm/string.hpp"
 
 #include "vm/jit/asmpart.h"
+#include "vm/jit/emit-common.hpp"
 #include "vm/jit/stubs.hpp"
 #include "vm/jit/trace.hpp"
 
@@ -441,53 +442,6 @@ bool builtin_checkcast(java_handle_t *o, classinfo *c)
 }
 
 
-/* builtin_descriptorscompatible ***********************************************
-
-   Checks if two array type descriptors are assignment compatible.
-
-   RETURN VALUE:
-      1......target = desc is possible
-      0......otherwise
-                       
-*******************************************************************************/
-
-static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
-{
-       if (desc == target)
-               return 1;
-
-       if (desc->arraytype != target->arraytype)
-               return 0;
-
-       if (desc->arraytype != ARRAYTYPE_OBJECT)
-               return 1;
-       
-       /* {both arrays are arrays of references} */
-
-       if (desc->dimension == target->dimension) {
-               if (!desc->elementvftbl)
-                       return 0;
-               /* an array which contains elements of interface types is
-           allowed to be casted to Object (JOWENN)*/
-
-               if ((desc->elementvftbl->baseval < 0) &&
-                       (target->elementvftbl->baseval == 1))
-                       return 1;
-
-               return class_isanysubclass(desc->elementvftbl->clazz,
-                                                                  target->elementvftbl->clazz);
-       }
-
-       if (desc->dimension < target->dimension)
-               return 0;
-
-       /* {desc has higher dimension than target} */
-
-       return class_isanysubclass(pseudo_class_Arraystub,
-                                                          target->elementvftbl->clazz);
-}
-
-
 /* builtin_arraycheckcast ******************************************************
 
    Checks if an object is really a subtype of the requested array
@@ -515,7 +469,7 @@ bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
        if (desc == NULL)
                return 0;
  
-       return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
+       return class_is_arraycompatible(desc, targetclass->vftbl->arraydesc);
 }
 
 
@@ -628,7 +582,7 @@ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
 
        LLNI_CRITICAL_START;
 
-       result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
+       result = builtin_fast_canstore((java_objectarray_t*) LLNI_DIRECT(oa), LLNI_UNWRAP(o));
 
        LLNI_CRITICAL_END;
 
@@ -640,6 +594,28 @@ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
        return result;
 }
 
+#if USES_NEW_SUBTYPE
+/* fast_subtype_check **********************************************************
+
+   Checks if s is a subtype of t, using both the restricted subtype relation
+   and the overflow array (see Cliff Click and John Rose: Fast subtype checking
+   in the Hotspot JVM.)
+
+   RETURN VALUE:
+      1......s is a subtype of t.
+      0......otherwise
+
+*******************************************************************************/
+
+bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
+{
+   if (s->subtype_display[t->subtype_depth] == t)
+       return true;
+   if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
+       return false;
+   return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
+}
+#endif
 
 /* builtin_fast_canstore *******************************************************
 
@@ -653,15 +629,6 @@ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
 
 *******************************************************************************/
 
-bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
-{
-       if (s->subtype_display[t->subtype_depth] == t)
-               return true;
-       if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
-               return false;
-       return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
-}
-
 bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
 {
        arraydescriptor *desc;
@@ -669,7 +636,6 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
        vftbl_t         *componentvftbl;
        vftbl_t         *valuevftbl;
        int32_t          baseval;
-       uint32_t         diffval;
        bool             result;
 
        if (o == NULL)
@@ -694,6 +660,8 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
                if (valuevftbl == componentvftbl)
                        return 1;
 
+               LOCK_CLASSRENUMBER_LOCK;
+
                baseval = componentvftbl->baseval;
 
                if (baseval <= 0) {
@@ -703,8 +671,15 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
                                          (valuevftbl->interfacetable[baseval] != NULL));
                }
                else {
+#if USES_NEW_SUBTYPE
                        result = fast_subtype_check(valuevftbl, componentvftbl);
+#else
+                       uint32_t diffval = valuevftbl->baseval - componentvftbl->baseval;
+                       result = diffval <= (uint32_t) componentvftbl->diffval;
+#endif
                }
+
+               UNLOCK_CLASSRENUMBER_LOCK;
        }
        else if (valuedesc == NULL) {
                /* {oa has dimension > 1} */
@@ -717,7 +692,7 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
        else {
                /* {o is an array} */
 
-               result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+               result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
        }
 
        /* return result */
@@ -733,7 +708,6 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
        vftbl_t         *elementvftbl;
        vftbl_t         *valuevftbl;
        int32_t          baseval;
-       uint32_t         diffval;
        bool             result;
        
        if (o == NULL)
@@ -756,6 +730,8 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
        if (valuevftbl == elementvftbl)
                return 1;
 
+       LOCK_CLASSRENUMBER_LOCK;
+
        baseval = elementvftbl->baseval;
 
        if (baseval <= 0) {
@@ -764,9 +740,16 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
                                  (valuevftbl->interfacetable[baseval] != NULL));
        }
        else {
+#if USES_NEW_SUBTYPE
                result = fast_subtype_check(valuevftbl, elementvftbl);
+#else
+               uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
+               result = diffval <= (uint32_t) elementvftbl->diffval;
+#endif
        }
 
+       UNLOCK_CLASSRENUMBER_LOCK;
+
        return result;
 }
 
@@ -775,10 +758,9 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
  * one-dimensional array of a class type */
 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
 {
-       vftbl_t  *elementvftbl;
-       vftbl_t  *valuevftbl;
-       uint32_t  diffval;
-       bool      result;
+       vftbl_t *elementvftbl;
+       vftbl_t *valuevftbl;
+       bool     result;
        
        if (o == NULL)
                return 1;
@@ -800,7 +782,16 @@ bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
        if (valuevftbl == elementvftbl)
                return 1;
 
+       LOCK_CLASSRENUMBER_LOCK;
+
+#if USES_NEW_SUBTYPE
        result = fast_subtype_check(valuevftbl, elementvftbl);
+#else
+       uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
+       result = diffval <= (uint32_t) elementvftbl->diffval;
+#endif
+
+       UNLOCK_CLASSRENUMBER_LOCK;
 
        return result;
 }
@@ -872,7 +863,7 @@ java_handle_t *builtin_new(classinfo *c)
        LLNI_vftbl_direct(o) = c->vftbl;
 
 #if defined(ENABLE_THREADS)
-       LLNI_DIRECT(o)->lockword.init();
+       Lockword(LLNI_DIRECT(o)->lockword).init();
 #endif
 
        CYCLES_STATS_GET(cycles_end);
@@ -954,7 +945,7 @@ java_handle_t *builtin_tlh_new(classinfo *c)
        LLNI_vftbl_direct(o) = c->vftbl;
 
 # if defined(ENABLE_THREADS)
-       LLNI_DIRECT(o)->lockword.init();
+       Lockword(LLNI_DIRECT(o)->lockword).init();
 # endif
 
        CYCLES_STATS_GET(cycles_end);
@@ -1033,7 +1024,7 @@ java_object_t *builtin_fast_new(classinfo *c)
        o->vftbl = c->vftbl;
 
 #if defined(ENABLE_THREADS)
-       LLNI_DIRECT(o)->lockword.init();
+       Lockword(LLNI_DIRECT(o)->lockword).init();
 #endif
 
        CYCLES_STATS_GET(cycles_end);
@@ -1046,7 +1037,7 @@ java_object_t *builtin_fast_new(classinfo *c)
 }
 
 
-/* builtin_newarray ************************************************************
+/* builtin_java_newarray *******************************************************
 
    Creates an array with the given vftbl on the heap. This function
    takes as class argument an array class.
@@ -1054,111 +1045,27 @@ java_object_t *builtin_fast_new(classinfo *c)
    RETURN VALUE:
       pointer to the array or NULL if no memory is available
 
-   NOTE: This builtin can be called from NATIVE code only.
+   NOTE: This is a SLOW builtin and can be called from JIT code only.
 
 *******************************************************************************/
 
-java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
+java_handle_array_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
 {
-       arraydescriptor *desc;
-       s4               dataoffset;
-       s4               componentsize;
-       s4               actualsize;
-       java_handle_t   *a;
 #if defined(ENABLE_RT_TIMING)
        struct timespec time_start, time_end;
 #endif
 
        RT_TIMING_GET_TIME(time_start);
 
-       desc          = arrayclass->vftbl->arraydesc;
-       dataoffset    = desc->dataoffset;
-       componentsize = desc->componentsize;
+       classinfo* arrayclass = LLNI_classinfo_unwrap(arrayclazz);
 
-       if (size < 0) {
-               exceptions_throw_negativearraysizeexception();
-               return NULL;
-       }
-
-       actualsize = dataoffset + size * componentsize;
-
-       /* check for overflow */
-
-       if (((u4) actualsize) < ((u4) size)) {
-               exceptions_throw_outofmemoryerror();
-               return NULL;
-       }
-
-       a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
-
-       if (a == NULL)
-               return NULL;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
-       /* XXX this is only a dirty hack to make Boehm work with handles */
-
-       a = LLNI_WRAP((java_object_t *) a);
-#endif
-
-       LLNI_vftbl_direct(a) = arrayclass->vftbl;
-
-#if defined(ENABLE_THREADS)
-       LLNI_DIRECT(a)->lockword.init();
-#endif
-
-       LLNI_array_size(a) = size;
+       // Allocate a new array with given size and class on the heap
+       Array a(size, arrayclass);
 
        RT_TIMING_GET_TIME(time_end);
        RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
 
-       return a;
-}
-
-
-/* builtin_java_newarray *******************************************************
-
-   NOTE: This is a SLOW builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
-{
-       return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
-}
-
-
-/* builtin_anewarray ***********************************************************
-
-   Creates an array of references to the given class type on the heap.
-
-   RETURN VALUE:
-      pointer to the array or NULL if no memory is
-      available
-
-   NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
-{
-       classinfo *arrayclass;
-       
-       /* is class loaded */
-
-       assert(componentclass->state & CLASS_LOADED);
-
-       /* is class linked */
-
-       if (!(componentclass->state & CLASS_LINKED))
-               if (!link_class(componentclass))
-                       return NULL;
-
-       arrayclass = class_array_of(componentclass, true);
-
-       if (!arrayclass)
-               return NULL;
-
-       return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
+       return a.get_handle();
 }
 
 
@@ -1173,21 +1080,21 @@ java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentc
 
 *******************************************************************************/
 
-#define BUILTIN_NEWARRAY_TYPE(type, arraytype)                             \
-java_handle_##type##array_t *builtin_newarray_##type(int32_t size)              \
-{                                                                          \
-       return (java_handle_##type##array_t *)                                 \
-               builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
+#define BUILTIN_NEWARRAY_TYPE(type, name)                          \
+java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
+{                                                                  \
+       name##Array a(size);                                           \
+       return a.get_handle();                                         \
 }
 
-BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
-BUILTIN_NEWARRAY_TYPE(byte,    ARRAYTYPE_BYTE)
-BUILTIN_NEWARRAY_TYPE(char,    ARRAYTYPE_CHAR)
-BUILTIN_NEWARRAY_TYPE(short,   ARRAYTYPE_SHORT)
-BUILTIN_NEWARRAY_TYPE(int,     ARRAYTYPE_INT)
-BUILTIN_NEWARRAY_TYPE(long,    ARRAYTYPE_LONG)
-BUILTIN_NEWARRAY_TYPE(float,   ARRAYTYPE_FLOAT)
-BUILTIN_NEWARRAY_TYPE(double,  ARRAYTYPE_DOUBLE)
+BUILTIN_NEWARRAY_TYPE(boolean, Boolean)
+BUILTIN_NEWARRAY_TYPE(byte,    Byte)
+BUILTIN_NEWARRAY_TYPE(char,    Char)
+BUILTIN_NEWARRAY_TYPE(short,   Short)
+BUILTIN_NEWARRAY_TYPE(int,     Int)
+BUILTIN_NEWARRAY_TYPE(long,    Long)
+BUILTIN_NEWARRAY_TYPE(float,   Float)
+BUILTIN_NEWARRAY_TYPE(double,  Double)
 
 
 /* builtin_multianewarray_intern ***********************************************
@@ -1205,38 +1112,37 @@ BUILTIN_NEWARRAY_TYPE(double,  ARRAYTYPE_DOUBLE)
 
 ******************************************************************************/
 
-static java_handle_t *builtin_multianewarray_intern(int n,
+static java_handle_array_t *builtin_multianewarray_intern(int n,
                                                                                                        classinfo *arrayclass,
                                                                                                        long *dims)
 {
-       s4             size;
-       java_handle_t *a;
-       classinfo     *componentclass;
-       s4             i;
+       int32_t i;
 
        /* create this dimension */
 
-       size = (s4) dims[0];
-       a = builtin_newarray(size, arrayclass);
+       int32_t size = (int32_t) dims[0];
+       Array a(size, arrayclass);
 
-       if (!a)
+       if (a.is_null())
                return NULL;
 
        /* if this is the last dimension return */
 
        if (!--n)
-               return a;
+               return a.get_handle();
 
        /* get the class of the components to create */
 
-       componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
+       classinfo* componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
 
        /* The verifier guarantees that the dimension count is in the range. */
 
        /* create the component arrays */
 
+       ObjectArray oa(a.get_handle());
+
        for (i = 0; i < size; i++) {
-               java_handle_t *ea =
+               java_handle_array_t *ea =
 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
                        /* we save an s4 to a s8 slot, 8-byte aligned */
 
@@ -1248,10 +1154,10 @@ static java_handle_t *builtin_multianewarray_intern(int n,
                if (!ea)
                        return NULL;
 
-               array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
+               oa.set_element(i, (java_handle_t*) ea);
        }
 
-       return a;
+       return a.get_handle();
 }
 
 
@@ -2096,6 +2002,9 @@ void builtin_arraycopy(java_handle_t *src, s4 srcStart,
                return;
        }
 
+       Array sa(src);
+       Array da(dest);
+
        sdesc = LLNI_vftbl_direct(src)->arraydesc;
        ddesc = LLNI_vftbl_direct(dest)->arraydesc;
 
@@ -2111,8 +2020,8 @@ void builtin_arraycopy(java_handle_t *src, s4 srcStart,
        }
 
        // Check if ranges are valid.
-       if ((((uint32_t) srcStart  + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
-               (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
+       if ((((uint32_t) srcStart  + (uint32_t) len) > (uint32_t) sa.get_length()) ||
+               (((uint32_t) destStart + (uint32_t) len) > (uint32_t) da.get_length())) {
                exceptions_throw_arrayindexoutofboundsexception();
                return;
        }
@@ -2139,19 +2048,17 @@ void builtin_arraycopy(java_handle_t *src, s4 srcStart,
        else {
                /* We copy references of different type */
 
-               java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
-               java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
+               ObjectArray oas((java_handle_objectarray_t*) src);
+               ObjectArray oad((java_handle_objectarray_t*) dest);
  
                if (destStart <= srcStart) {
                        for (i = 0; i < len; i++) {
-                               java_handle_t *o;
+                               java_handle_t* o = oas.get_element(srcStart + i);
 
-                               o = array_objectarray_element_get(oas, srcStart + i);
-
-                               if (!builtin_canstore(oad, o))
+                               if (!builtin_canstore(oad.get_handle(), o))
                                        return;
 
-                               array_objectarray_element_set(oad, destStart + i, o);
+                               oad.set_element(destStart + i, o);
                        }
                }
                else {
@@ -2162,14 +2069,12 @@ void builtin_arraycopy(java_handle_t *src, s4 srcStart,
                           index have been copied before the throw. */
 
                        for (i = len - 1; i >= 0; i--) {
-                               java_handle_t *o;
-
-                               o = array_objectarray_element_get(oas, srcStart + i);
+                               java_handle_t* o = oas.get_element(srcStart + i);
 
-                               if (!builtin_canstore(oad, o))
+                               if (!builtin_canstore(oad.get_handle(), o))
                                        return;
 
-                               array_objectarray_element_set(oad, destStart + i, o);
+                               oad.set_element(destStart + i, o);
                        }
                }
        }
@@ -2234,7 +2139,9 @@ java_handle_t *builtin_clone(void *env, java_handle_t *o)
        /* we are cloning an array */
 
        if (ad != NULL) {
-               size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
+               Array a(o);
+
+               size = ad->dataoffset + ad->componentsize * a.get_length();
         
                co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
 
@@ -2256,7 +2163,7 @@ java_handle_t *builtin_clone(void *env, java_handle_t *o)
 #endif
 
 #if defined(ENABLE_THREADS)
-               LLNI_DIRECT(co)->lockword.init();
+               Lockword(LLNI_DIRECT(co)->lockword).init();
 #endif
 
                LLNI_CRITICAL_END;
@@ -2291,7 +2198,7 @@ java_handle_t *builtin_clone(void *env, java_handle_t *o)
 #endif
 
 #if defined(ENABLE_THREADS)
-       LLNI_DIRECT(co)->lockword.init();
+       Lockword(LLNI_DIRECT(co)->lockword).init();
 #endif
 
        LLNI_CRITICAL_END;