* src/vm/array.hpp: Implemented array access classes in C++.
[cacao.git] / src / vm / array.hpp
1 /* src/vm/array.hpp - Java array functions
2
3    Copyright (C) 2007
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5    Copyright (C) 2008 Theobroma Systems Ltd.
6
7    This file is part of CACAO.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2, or (at
12    your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22    02110-1301, USA.
23
24 */
25
26
27 #ifndef _VM_ARRAY_HPP
28 #define _VM_ARRAY_HPP
29
30 #include "config.h"
31
32 #include <stdint.h>
33
34 #include "mm/gc.hpp" // XXX Remove me!
35
36 #include "native/llni.h" // XXX Remove me!
37
38 #include "vm/class.hpp"
39 #include "vm/exceptions.hpp"
40 #include "vm/global.h"
41 #include "vm/primitive.hpp"
42
43
44 /* array types ****************************************************************/
45
46 /* CAUTION: Don't change the numerical values! These constants (with
47    the exception of ARRAYTYPE_OBJECT) are used as indices in the
48    primitive type table. */
49
50 #define ARRAYTYPE_INT         PRIMITIVETYPE_INT
51 #define ARRAYTYPE_LONG        PRIMITIVETYPE_LONG
52 #define ARRAYTYPE_FLOAT       PRIMITIVETYPE_FLOAT
53 #define ARRAYTYPE_DOUBLE      PRIMITIVETYPE_DOUBLE
54 #define ARRAYTYPE_BYTE        PRIMITIVETYPE_BYTE
55 #define ARRAYTYPE_CHAR        PRIMITIVETYPE_CHAR
56 #define ARRAYTYPE_SHORT       PRIMITIVETYPE_SHORT
57 #define ARRAYTYPE_BOOLEAN     PRIMITIVETYPE_BOOLEAN
58 #define ARRAYTYPE_OBJECT      PRIMITIVETYPE_VOID     /* don't use as index! */
59
60
61 #ifdef __cplusplus
62
63 /**
64  * This is a generic accessor class for Java arrays (of unspecified type),
65  * which can be used to safely operate on Java arrays in native code.
66  */
67 class Array {
68 protected:
69         // Handle of Java array.
70         java_handle_array_t* _handle;
71
72 private:
73         // We don't want a Java arrays to be copied.
74         Array(Array* a) {}
75         Array(Array& a) {}
76
77 public:
78         inline Array(java_handle_t* h);
79         inline Array(int32_t length, classinfo* arrayclass);
80         virtual ~Array() {}
81
82         // Getters.
83         virtual inline java_handle_array_t* get_handle() const { return _handle; }
84         inline int32_t                      get_length() const;
85
86         inline bool is_null    () const;
87         inline bool is_non_null() const;
88
89         // Safe element modification functions for primitive values
90         imm_union get_primitive_element(int32_t index);
91         void      set_primitive_element(int32_t index, imm_union value);
92
93         // Safe element modification functions for boxed values
94         java_handle_t* get_boxed_element(int32_t index);
95         void           set_boxed_element(int32_t index, java_handle_t *o);
96
97         // XXX REMOVE ME!
98         inline void* get_raw_data_ptr() { return ((java_objectarray_t*) _handle)->data; }
99 };
100
101
102 /**
103  * Constructor checks if passed handle really is a Java array.
104  */
105 inline Array::Array(java_handle_t* h)
106 {
107         if (h == NULL) {
108                 _handle = NULL;
109                 return;
110         }
111
112 #if 0
113         classinfo* c;
114         LLNI_class_get(h, c);
115         if (!class_is_array(c)) {
116                 printf("Array::Array(): WARNING, passed handle is not an array\n");
117                 //exceptions_throw_illegalargumentexception("Argument is not an array");
118                 exceptions_throw_illegalargumentexception();
119                 _handle = NULL;
120                 return;
121         }
122 #endif
123
124         _handle = h;
125 }
126
127 /**
128  * Creates an array of the given array type on the heap.
129  * The handle pointer to the array can be NULL in case of an exception.
130  */
131 inline Array::Array(int32_t size, classinfo* arrayclass)
132 {
133         // Sanity check.
134         assert(class_is_array(arrayclass));
135
136         if (size < 0) {
137                 exceptions_throw_negativearraysizeexception();
138                 _handle = NULL;
139                 return;
140         }
141
142         arraydescriptor* desc          = arrayclass->vftbl->arraydesc;
143         int32_t          dataoffset    = desc->dataoffset;
144         int32_t          componentsize = desc->componentsize;
145         int32_t          actualsize    = dataoffset + size * componentsize;
146
147         // Check for overflow.
148
149         if (((u4) actualsize) < ((u4) size)) {
150                 exceptions_throw_outofmemoryerror();
151                 _handle = NULL;
152                 return;
153         }
154
155         java_array_t* a = (java_array_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
156
157         if (a == NULL) {
158                 _handle = NULL;
159                 return;
160         }
161
162         LLNI_vftbl_direct(a) = arrayclass->vftbl;
163
164 #if defined(ENABLE_THREADS)
165         a->objheader.lockword.init();
166 #endif
167
168         a->size = size;
169
170         _handle = (java_handle_array_t*) a;
171 }
172
173 inline int32_t Array::get_length() const
174 {
175         if (is_null()) {
176                 printf("Array::get_length(): WARNING, got null-pointer\n");
177                 exceptions_throw_nullpointerexception();
178                 return -1;
179         }
180
181         // XXX Fix me!
182         int32_t length = ((java_array_t*) _handle)->size;
183
184         return length;
185 }
186
187 inline bool Array::is_null() const
188 {
189         return (_handle == NULL);
190 }
191
192 inline bool Array::is_non_null() const
193 {
194         return (_handle != NULL);
195 }
196
197
198 /**
199  * This is a template of an accessor class for Java arrays
200  * of a specific type.
201  */
202 template<class T> class ArrayTemplate : public Array {
203 protected:
204         ArrayTemplate(int32_t length, classinfo* arrayclass) : Array(length, arrayclass) {}
205
206 public:
207         inline ArrayTemplate(java_handle_array_t* h) : Array(h) {}
208
209         // Safe element modification functions
210         inline T    get_element(int32_t index);
211         inline void set_element(int32_t index, T value);
212
213         // Region copy functions
214         inline void get_region(int32_t offset, int32_t count, T* buffer);
215         inline void set_region(int32_t offset, int32_t count, const T* buffer);
216 };
217
218
219 template<class T> inline T ArrayTemplate<T>::get_element(int32_t index)
220 {
221         if (is_null()) {
222                 exceptions_throw_nullpointerexception();
223                 return 0;
224         }
225
226         if ((index < 0) || (index >= get_length())) {
227                 exceptions_throw_arrayindexoutofboundsexception();
228                 return 0;
229         }
230
231         // XXX Fix me!
232         T* ptr = (T*) get_raw_data_ptr();
233
234         return ptr[index];
235 }
236
237 template<class T> inline void ArrayTemplate<T>::set_element(int32_t index, T value)
238 {
239         if (is_null()) {
240                 exceptions_throw_nullpointerexception();
241                 return;
242         }
243
244         if ((index < 0) || (index >= get_length())) {
245                 exceptions_throw_arrayindexoutofboundsexception();
246                 return;
247         }
248
249         // XXX Fix me!
250         T* ptr = (T*) get_raw_data_ptr();
251
252         ptr[index] = value;
253 }
254
255 template<> inline void ArrayTemplate<java_handle_t*>::set_element(int32_t index, java_handle_t* value)
256 {
257         if (is_null()) {
258                 exceptions_throw_nullpointerexception();
259                 return;
260         }
261
262         // Sanity check.
263         assert(((java_array_t*) _handle)->objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT);
264
265         // Check if value can be stored
266         if (value != NULL) {
267                 if (builtin_canstore(get_handle(), value) == false) {
268                         exceptions_throw_illegalargumentexception();
269                         return;
270                 }
271         }
272
273         if ((index < 0) || (index >= get_length())) {
274                 exceptions_throw_arrayindexoutofboundsexception();
275                 return;
276         }
277
278         // XXX Fix me!
279         java_handle_t** ptr = (java_handle_t**) get_raw_data_ptr();
280
281         ptr[index] = value;
282 }
283
284 template<class T> inline void ArrayTemplate<T>::get_region(int32_t offset, int32_t count, T* buffer)
285 {
286         // Copy the array region inside a GC critical section.
287         GCCriticalSection cs;
288
289         // XXX Fix me!
290         const T* ptr = (T*) get_raw_data_ptr();
291
292         os::memcpy(buffer, ptr + offset, sizeof(T) * count);
293 }
294
295 template<class T> inline void ArrayTemplate<T>::set_region(int32_t offset, int32_t count, const T* buffer)
296 {
297         // Copy the array region inside a GC critical section.
298         GCCriticalSection cs;
299
300         // XXX Fix me!
301         T* ptr = (T*) get_raw_data_ptr();
302
303         os::memcpy(ptr + offset, buffer, sizeof(T) * count);
304 }
305
306
307 /**
308  * Actual implementations of common Java array access classes.
309  */
310 class BooleanArray : public ArrayTemplate<uint8_t> {
311 public:
312         inline BooleanArray(java_handle_booleanarray_t* h) : ArrayTemplate<uint8_t>(h) {}
313         inline BooleanArray(int32_t length) : ArrayTemplate<uint8_t>(length, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass) {}
314 };
315
316 class ByteArray : public ArrayTemplate<int8_t> {
317 public:
318         inline ByteArray(java_handle_bytearray_t* h) : ArrayTemplate<int8_t>(h) {}
319         inline ByteArray(int32_t length) : ArrayTemplate<int8_t>(length, primitivetype_table[ARRAYTYPE_BYTE].arrayclass) {}
320 };
321
322 class CharArray : public ArrayTemplate<uint16_t> {
323 public:
324         inline CharArray(java_handle_chararray_t* h) : ArrayTemplate<uint16_t>(h) {}
325         inline CharArray(int32_t length) : ArrayTemplate<uint16_t>(length, primitivetype_table[ARRAYTYPE_CHAR].arrayclass) {}
326 };
327
328 class ShortArray : public ArrayTemplate<int16_t> {
329 public:
330         inline ShortArray(java_handle_shortarray_t* h) : ArrayTemplate<int16_t>(h) {}
331         inline ShortArray(int32_t length) : ArrayTemplate<int16_t>(length, primitivetype_table[ARRAYTYPE_SHORT].arrayclass) {}
332 };
333
334 class IntArray : public ArrayTemplate<int32_t> {
335 public:
336         inline IntArray(java_handle_intarray_t* h) : ArrayTemplate<int32_t>(h) {}
337         inline IntArray(int32_t length) : ArrayTemplate<int32_t>(length, primitivetype_table[ARRAYTYPE_INT].arrayclass) {}
338 };
339
340 class LongArray : public ArrayTemplate<int64_t> {
341 public:
342         inline LongArray(java_handle_longarray_t* h) : ArrayTemplate<int64_t>(h) {}
343         inline LongArray(int32_t length) : ArrayTemplate<int64_t>(length, primitivetype_table[ARRAYTYPE_LONG].arrayclass) {}
344 };
345
346 class FloatArray : public ArrayTemplate<float> {
347 public:
348         inline FloatArray(java_handle_floatarray_t* h) : ArrayTemplate<float>(h) {}
349         inline FloatArray(int32_t length) : ArrayTemplate<float>(length, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass) {}
350 };
351
352 class DoubleArray : public ArrayTemplate<double> {
353 public:
354         inline DoubleArray(java_handle_doublearray_t* h) : ArrayTemplate<double>(h) {}
355         inline DoubleArray(int32_t length) : ArrayTemplate<double>(length, primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass) {}
356 };
357
358 /**
359  * Actual implementation of access class for Java Object arrays.
360  */
361 class ObjectArray : public ArrayTemplate<java_handle_t*> {
362 public:
363         inline ObjectArray(java_handle_objectarray_t* h) : ArrayTemplate<java_handle_t*>(h) {}
364         ObjectArray(int32_t length, classinfo* componentclass);
365 };
366
367 /**
368  * Actual implementation of access class for java.lang.Class arrays.
369  */
370 class ClassArray : public ArrayTemplate<classinfo*> {
371 public:
372         ClassArray(int32_t length);
373 };
374
375
376 #else
377 # warning No legacy C functions for array access classes.
378 #endif
379
380 #endif // _VM_ARRAY_HPP
381
382
383 /*
384  * These are local overrides for various environment variables in Emacs.
385  * Please do not remove this and leave it at the end of the file, where
386  * Emacs will automagically detect them.
387  * ---------------------------------------------------------------------
388  * Local variables:
389  * mode: c++
390  * indent-tabs-mode: t
391  * c-basic-offset: 4
392  * tab-width: 4
393  * End:
394  * vim:noexpandtab:sw=4:ts=4:
395  */