X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Farray.hpp;h=06813aee46bf560c1f860d38c7c069dbe42666b6;hb=d75c5c294648344a83d3a1df07695e1123a84f79;hp=86f10843b0577087540bd676724f1af76e020742;hpb=7d9438705087944b53d2291820d1c8f729dad833;p=cacao.git diff --git a/src/vm/array.hpp b/src/vm/array.hpp index 86f10843b..06813aee4 100644 --- a/src/vm/array.hpp +++ b/src/vm/array.hpp @@ -2,6 +2,7 @@ Copyright (C) 2007 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2008 Theobroma Systems Ltd. This file is part of CACAO. @@ -30,6 +31,12 @@ #include +#include "mm/gc.hpp" // XXX Remove me! + +#include "native/llni.h" // XXX Remove me! + +#include "vm/class.hpp" +#include "vm/exceptions.hpp" #include "vm/global.h" #include "vm/primitive.hpp" @@ -51,42 +58,323 @@ #define ARRAYTYPE_OBJECT PRIMITIVETYPE_VOID /* don't use as index! */ -/* function prototypes ********************************************************/ - #ifdef __cplusplus -extern "C" { + +/** + * This is a generic accessor class for Java arrays (of unspecified type), + * which can be used to safely operate on Java arrays in native code. + */ +class Array { +protected: + // Handle of Java array. + java_handle_array_t* _handle; + +private: + // We don't want a Java arrays to be copied. + Array(Array* a) {} + Array(Array& a) {} + +public: + inline Array(java_handle_t* h); + inline Array(int32_t length, classinfo* arrayclass); + virtual ~Array() {} + + // Getters. + virtual inline java_handle_array_t* get_handle() const { return _handle; } + inline int32_t get_length() const; + + inline bool is_null () const; + inline bool is_non_null() const; + + // Safe element modification functions for primitive values + imm_union get_primitive_element(int32_t index); + void set_primitive_element(int32_t index, imm_union value); + + // Safe element modification functions for boxed values + java_handle_t* get_boxed_element(int32_t index); + void set_boxed_element(int32_t index, java_handle_t *o); + + // XXX REMOVE ME! + inline void* get_raw_data_ptr() { return ((java_objectarray_t*) _handle)->data; } +}; + + +/** + * Constructor checks if passed handle really is a Java array. + */ +inline Array::Array(java_handle_t* h) +{ + if (h == NULL) { + _handle = NULL; + return; + } + +#if 0 + classinfo* c; + LLNI_class_get(h, c); + if (!class_is_array(c)) { + printf("Array::Array(): WARNING, passed handle is not an array\n"); + //exceptions_throw_illegalargumentexception("Argument is not an array"); + exceptions_throw_illegalargumentexception(); + _handle = NULL; + return; + } #endif -java_handle_t *array_element_get(java_handle_t *a, int32_t index); -void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o); - -imm_union array_element_primitive_get(java_handle_t *a, int32_t index); -void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value); - -uint8_t array_booleanarray_element_get(java_handle_booleanarray_t *a, int32_t index); -int8_t array_bytearray_element_get(java_handle_bytearray_t *a, int32_t index); -uint16_t array_chararray_element_get(java_handle_chararray_t *a, int32_t index); -int16_t array_shortarray_element_get(java_handle_shortarray_t *a, int32_t index); -int32_t array_intarray_element_get(java_handle_intarray_t *a, int32_t index); -int64_t array_longarray_element_get(java_handle_longarray_t *a, int32_t index); -float array_floatarray_element_get(java_handle_floatarray_t *a, int32_t index); -double array_doublearray_element_get(java_handle_doublearray_t *a, int32_t index); -java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index); - -void array_booleanarray_element_set(java_handle_booleanarray_t *a, int32_t index, uint8_t value); -void array_bytearray_element_set(java_handle_bytearray_t *a, int32_t index, int8_t value); -void array_chararray_element_set(java_handle_chararray_t *a, int32_t index, uint16_t value); -void array_shortarray_element_set(java_handle_shortarray_t *a, int32_t index, int16_t value); -void array_intarray_element_set(java_handle_intarray_t *a, int32_t index, int32_t value); -void array_longarray_element_set(java_handle_longarray_t *a, int32_t index, int64_t value); -void array_floatarray_element_set(java_handle_floatarray_t *a, int32_t index, float value); -void array_doublearray_element_set(java_handle_doublearray_t *a, int32_t index, double value); -void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value); - -int32_t array_length_get(java_handle_t *a); + _handle = h; +} -#ifdef __cplusplus -} // extern "C" +/** + * Creates an array of the given array type on the heap. + * The handle pointer to the array can be NULL in case of an exception. + */ +inline Array::Array(int32_t size, classinfo* arrayclass) +{ + // Sanity check. + assert(class_is_array(arrayclass)); + + if (size < 0) { + exceptions_throw_negativearraysizeexception(); + _handle = NULL; + return; + } + + arraydescriptor* desc = arrayclass->vftbl->arraydesc; + int32_t dataoffset = desc->dataoffset; + int32_t componentsize = desc->componentsize; + int32_t actualsize = dataoffset + size * componentsize; + + // Check for overflow. + + if (((u4) actualsize) < ((u4) size)) { + exceptions_throw_outofmemoryerror(); + _handle = NULL; + return; + } + + java_array_t* a = (java_array_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true); + + if (a == NULL) { + _handle = NULL; + return; + } + + LLNI_vftbl_direct(a) = arrayclass->vftbl; + +#if defined(ENABLE_THREADS) + a->objheader.lockword.init(); +#endif + + a->size = size; + + _handle = (java_handle_array_t*) a; +} + +inline int32_t Array::get_length() const +{ + if (is_null()) { + printf("Array::get_length(): WARNING, got null-pointer\n"); + exceptions_throw_nullpointerexception(); + return -1; + } + + // XXX Fix me! + int32_t length = ((java_array_t*) _handle)->size; + + return length; +} + +inline bool Array::is_null() const +{ + return (_handle == NULL); +} + +inline bool Array::is_non_null() const +{ + return (_handle != NULL); +} + + +/** + * This is a template of an accessor class for Java arrays + * of a specific type. + */ +template class ArrayTemplate : public Array { +protected: + ArrayTemplate(int32_t length, classinfo* arrayclass) : Array(length, arrayclass) {} + +public: + inline ArrayTemplate(java_handle_array_t* h) : Array(h) {} + + // Safe element modification functions + inline T get_element(int32_t index); + inline void set_element(int32_t index, T value); + + // Region copy functions + inline void get_region(int32_t offset, int32_t count, T* buffer); + inline void set_region(int32_t offset, int32_t count, const T* buffer); +}; + + +template inline T ArrayTemplate::get_element(int32_t index) +{ + if (is_null()) { + exceptions_throw_nullpointerexception(); + return 0; + } + + if ((index < 0) || (index >= get_length())) { + exceptions_throw_arrayindexoutofboundsexception(); + return 0; + } + + // XXX Fix me! + T* ptr = (T*) get_raw_data_ptr(); + + return ptr[index]; +} + +template inline void ArrayTemplate::set_element(int32_t index, T value) +{ + if (is_null()) { + exceptions_throw_nullpointerexception(); + return; + } + + if ((index < 0) || (index >= get_length())) { + exceptions_throw_arrayindexoutofboundsexception(); + return; + } + + // XXX Fix me! + T* ptr = (T*) get_raw_data_ptr(); + + ptr[index] = value; +} + +template<> inline void ArrayTemplate::set_element(int32_t index, java_handle_t* value) +{ + if (is_null()) { + exceptions_throw_nullpointerexception(); + return; + } + + // Sanity check. + assert(((java_array_t*) _handle)->objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT); + + // Check if value can be stored + if (value != NULL) { + if (builtin_canstore(get_handle(), value) == false) { + exceptions_throw_illegalargumentexception(); + return; + } + } + + if ((index < 0) || (index >= get_length())) { + exceptions_throw_arrayindexoutofboundsexception(); + return; + } + + // XXX Fix me! + java_handle_t** ptr = (java_handle_t**) get_raw_data_ptr(); + + ptr[index] = value; +} + +template inline void ArrayTemplate::get_region(int32_t offset, int32_t count, T* buffer) +{ + // Copy the array region inside a GC critical section. + GCCriticalSection cs; + + // XXX Fix me! + const T* ptr = (T*) get_raw_data_ptr(); + + os::memcpy(buffer, ptr + offset, sizeof(T) * count); +} + +template inline void ArrayTemplate::set_region(int32_t offset, int32_t count, const T* buffer) +{ + // Copy the array region inside a GC critical section. + GCCriticalSection cs; + + // XXX Fix me! + T* ptr = (T*) get_raw_data_ptr(); + + os::memcpy(ptr + offset, buffer, sizeof(T) * count); +} + + +/** + * Actual implementations of common Java array access classes. + */ +class BooleanArray : public ArrayTemplate { +public: + inline BooleanArray(java_handle_booleanarray_t* h) : ArrayTemplate(h) {} + inline BooleanArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass) {} +}; + +class ByteArray : public ArrayTemplate { +public: + inline ByteArray(java_handle_bytearray_t* h) : ArrayTemplate(h) {} + inline ByteArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_BYTE].arrayclass) {} +}; + +class CharArray : public ArrayTemplate { +public: + inline CharArray(java_handle_chararray_t* h) : ArrayTemplate(h) {} + inline CharArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_CHAR].arrayclass) {} +}; + +class ShortArray : public ArrayTemplate { +public: + inline ShortArray(java_handle_shortarray_t* h) : ArrayTemplate(h) {} + inline ShortArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_SHORT].arrayclass) {} +}; + +class IntArray : public ArrayTemplate { +public: + inline IntArray(java_handle_intarray_t* h) : ArrayTemplate(h) {} + inline IntArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_INT].arrayclass) {} +}; + +class LongArray : public ArrayTemplate { +public: + inline LongArray(java_handle_longarray_t* h) : ArrayTemplate(h) {} + inline LongArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_LONG].arrayclass) {} +}; + +class FloatArray : public ArrayTemplate { +public: + inline FloatArray(java_handle_floatarray_t* h) : ArrayTemplate(h) {} + inline FloatArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass) {} +}; + +class DoubleArray : public ArrayTemplate { +public: + inline DoubleArray(java_handle_doublearray_t* h) : ArrayTemplate(h) {} + inline DoubleArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass) {} +}; + +/** + * Actual implementation of access class for Java Object arrays. + */ +class ObjectArray : public ArrayTemplate { +public: + inline ObjectArray(java_handle_objectarray_t* h) : ArrayTemplate(h) {} + ObjectArray(int32_t length, classinfo* componentclass); +}; + +/** + * Actual implementation of access class for java.lang.Class arrays. + */ +class ClassArray : public ArrayTemplate { +public: + ClassArray(int32_t length); +}; + + +#else +# warning No legacy C functions for array access classes. #endif #endif // _VM_ARRAY_HPP