/* 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.
#endif
#include "mm/gc.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/llni.h"
#include "threads/mutex.hpp"
#include "threads/thread.hpp"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "toolbox/util.h"
#include "vm/array.hpp"
#include "vm/jit/builtin.hpp"
-#include "vm/class.h"
+#include "vm/class.hpp"
#include "vm/cycles-stats.h"
#include "vm/exceptions.hpp"
#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"
#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"
}
-/* 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
if (desc == NULL)
return 0;
- return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
+ return class_is_arraycompatible(desc, targetclass->vftbl->arraydesc);
}
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;
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 *******************************************************
vftbl_t *componentvftbl;
vftbl_t *valuevftbl;
int32_t baseval;
- uint32_t diffval;
bool result;
if (o == NULL)
if (valuevftbl == componentvftbl)
return 1;
- linker_classrenumber_mutex->lock();
+ LOCK_CLASSRENUMBER_LOCK;
baseval = componentvftbl->baseval;
(valuevftbl->interfacetable[baseval] != NULL));
}
else {
- diffval = valuevftbl->baseval - componentvftbl->baseval;
- result = diffval <= (uint32_t) componentvftbl->diffval;
+#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
}
- linker_classrenumber_mutex->unlock();
+ UNLOCK_CLASSRENUMBER_LOCK;
}
else if (valuedesc == NULL) {
/* {oa has dimension > 1} */
else {
/* {o is an array} */
- result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+ result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
}
/* return result */
vftbl_t *elementvftbl;
vftbl_t *valuevftbl;
int32_t baseval;
- uint32_t diffval;
bool result;
if (o == NULL)
if (valuevftbl == elementvftbl)
return 1;
- linker_classrenumber_mutex->lock();
+ LOCK_CLASSRENUMBER_LOCK;
baseval = elementvftbl->baseval;
(valuevftbl->interfacetable[baseval] != NULL));
}
else {
- diffval = valuevftbl->baseval - elementvftbl->baseval;
- result = diffval <= (uint32_t) elementvftbl->diffval;
+#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
}
- linker_classrenumber_mutex->unlock();
+ UNLOCK_CLASSRENUMBER_LOCK;
return result;
}
* 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;
if (valuevftbl == elementvftbl)
return 1;
- linker_classrenumber_mutex->lock();
+ LOCK_CLASSRENUMBER_LOCK;
- diffval = valuevftbl->baseval - elementvftbl->baseval;
- result = diffval <= (uint32_t) elementvftbl->diffval;
+#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
- linker_classrenumber_mutex->unlock();
+ UNLOCK_CLASSRENUMBER_LOCK;
return result;
}
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);
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);
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);
}
-/* builtin_newarray ************************************************************
+/* builtin_java_newarray *******************************************************
Creates an array with the given vftbl on the heap. This function
takes as class argument an array class.
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;
-
- 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
+ classinfo* arrayclass = LLNI_classinfo_unwrap(arrayclazz);
- 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();
}
*******************************************************************************/
-#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 ***********************************************
******************************************************************************/
-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 */
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();
}
return;
}
+ Array sa(src);
+ Array da(dest);
+
sdesc = LLNI_vftbl_direct(src)->arraydesc;
ddesc = LLNI_vftbl_direct(dest)->arraydesc;
}
// 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;
}
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 {
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);
}
}
}
/* 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);
#endif
#if defined(ENABLE_THREADS)
- LLNI_DIRECT(co)->lockword.init();
+ Lockword(LLNI_DIRECT(co)->lockword).init();
#endif
LLNI_CRITICAL_END;
#endif
#if defined(ENABLE_THREADS)
- LLNI_DIRECT(co)->lockword.init();
+ Lockword(LLNI_DIRECT(co)->lockword).init();
#endif
LLNI_CRITICAL_END;