+/**
+ * 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)
+ Lockword(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 T> class ArrayTemplate : public Array {
+protected:
+ ArrayTemplate(int32_t length, classinfo* arrayclass) : Array(length, arrayclass) {}
+
+public:
+ ArrayTemplate(java_handle_array_t* h) : Array(h) {}
+
+ // XXX This should be protected or private!
+ virtual T* get_raw_data_ptr() = 0;
+
+ // Safe element modification functions
+ T get_element(int32_t index);
+ void set_element(int32_t index, T value);
+
+ // Region copy functions
+ void get_region(int32_t offset, int32_t count, T* buffer);
+ void set_region(int32_t offset, int32_t count, const T* buffer);
+};
+
+
+template<class T> inline T ArrayTemplate<T>::get_element(int32_t index)
+{
+ if (is_null()) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ if ((index < 0) || (index >= get_length())) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return 0;
+ }
+
+ T* ptr = get_raw_data_ptr();
+
+ return ptr[index];
+}
+
+template<class T> inline void ArrayTemplate<T>::set_element(int32_t index, T value)
+{
+ if (is_null()) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ if ((index < 0) || (index >= get_length())) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return;
+ }
+
+ T* ptr = get_raw_data_ptr();
+
+ ptr[index] = value;
+}
+
+template<> inline void ArrayTemplate<java_handle_t*>::set_element(int32_t index, java_handle_t* value)
+{
+ if (is_null()) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ // Sanity check.
+ assert(((java_array_t*) get_handle())->objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT);
+
+ // Check if value can be stored
+ if (!builtin_canstore(get_handle(), value)) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ if ((index < 0) || (index >= get_length())) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return;
+ }
+
+ java_handle_t** ptr = get_raw_data_ptr();
+
+ ptr[index] = value;
+}
+
+template<class T> inline void ArrayTemplate<T>::get_region(int32_t offset, int32_t count, T* buffer)
+{
+ // Copy the array region inside a GC critical section.
+ GCCriticalSection cs;
+
+ const T* ptr = get_raw_data_ptr();
+
+ os::memcpy(buffer, ptr + offset, sizeof(T) * count);
+}
+
+template<class T> inline void ArrayTemplate<T>::set_region(int32_t offset, int32_t count, const T* buffer)
+{
+ // Copy the array region inside a GC critical section.
+ GCCriticalSection cs;
+
+ T* ptr = get_raw_data_ptr();
+
+ os::memcpy(ptr + offset, buffer, sizeof(T) * count);
+}
+
+
+/**
+ * Actual implementations of common Java array access classes.
+ */
+class BooleanArray : public ArrayTemplate<uint8_t> {
+public:
+ BooleanArray(java_handle_booleanarray_t* h) : ArrayTemplate<uint8_t>(h) {}
+ BooleanArray(int32_t length) : ArrayTemplate<uint8_t>(length, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass) {}
+ uint8_t* get_raw_data_ptr() { return ((java_booleanarray_t*) get_handle())->data; }
+};
+
+class ByteArray : public ArrayTemplate<int8_t> {
+public:
+ ByteArray(java_handle_bytearray_t* h) : ArrayTemplate<int8_t>(h) {}
+ ByteArray(int32_t length) : ArrayTemplate<int8_t>(length, primitivetype_table[ARRAYTYPE_BYTE].arrayclass) {}
+ int8_t* get_raw_data_ptr() { return (int8_t*) ((java_bytearray_t*) get_handle())->data; }
+};
+
+class CharArray : public ArrayTemplate<uint16_t> {
+public:
+ CharArray(java_handle_chararray_t* h) : ArrayTemplate<uint16_t>(h) {}
+ CharArray(int32_t length) : ArrayTemplate<uint16_t>(length, primitivetype_table[ARRAYTYPE_CHAR].arrayclass) {}
+ uint16_t* get_raw_data_ptr() { return ((java_chararray_t*) get_handle())->data; }
+};
+
+class ShortArray : public ArrayTemplate<int16_t> {
+public:
+ ShortArray(java_handle_shortarray_t* h) : ArrayTemplate<int16_t>(h) {}
+ ShortArray(int32_t length) : ArrayTemplate<int16_t>(length, primitivetype_table[ARRAYTYPE_SHORT].arrayclass) {}
+ int16_t* get_raw_data_ptr() { return ((java_shortarray_t*) get_handle())->data; }
+};
+
+class IntArray : public ArrayTemplate<int32_t> {
+public:
+ IntArray(java_handle_intarray_t* h) : ArrayTemplate<int32_t>(h) {}
+ IntArray(int32_t length) : ArrayTemplate<int32_t>(length, primitivetype_table[ARRAYTYPE_INT].arrayclass) {}
+ int32_t* get_raw_data_ptr() { return ((java_intarray_t*) get_handle())->data; }
+};
+
+class LongArray : public ArrayTemplate<int64_t> {
+public:
+ LongArray(java_handle_longarray_t* h) : ArrayTemplate<int64_t>(h) {}
+ LongArray(int32_t length) : ArrayTemplate<int64_t>(length, primitivetype_table[ARRAYTYPE_LONG].arrayclass) {}
+ int64_t* get_raw_data_ptr() { return ((java_longarray_t*) get_handle())->data; }
+};
+
+class FloatArray : public ArrayTemplate<float> {
+public:
+ FloatArray(java_handle_floatarray_t* h) : ArrayTemplate<float>(h) {}
+ FloatArray(int32_t length) : ArrayTemplate<float>(length, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass) {}
+ float* get_raw_data_ptr() { return ((java_floatarray_t*) get_handle())->data; }
+};
+
+class DoubleArray : public ArrayTemplate<double> {
+public:
+ DoubleArray(java_handle_doublearray_t* h) : ArrayTemplate<double>(h) {}
+ DoubleArray(int32_t length) : ArrayTemplate<double>(length, primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass) {}
+ double* get_raw_data_ptr() { return ((java_doublearray_t*) get_handle())->data; }
+};
+
+/**
+ * Actual implementation of access class for Java Object arrays.
+ */
+class ObjectArray : public ArrayTemplate<java_handle_t*> {
+public:
+ ObjectArray(java_handle_objectarray_t* h) : ArrayTemplate<java_handle_t*>(h) {}
+ ObjectArray(int32_t length, classinfo* componentclass);
+ java_handle_t** get_raw_data_ptr() { return ((java_objectarray_t*) get_handle())->data; }
+};
+
+/**
+ * Actual implementation of access class for java.lang.Class arrays.
+ */
+class ClassArray : public ArrayTemplate<classinfo*> {
+public:
+ ClassArray(int32_t length);
+ classinfo** get_raw_data_ptr() { return (classinfo**) ((java_objectarray_t*) get_handle())->data; }
+};
+
+
+#else
+# warning No legacy C functions for array access classes.