Line data Source code
1 : /* src/vm/array.hpp - Java array functions
2 :
3 : Copyright (C) 1996-2014
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 ARRAY_HPP_
28 : #define ARRAY_HPP_ 1
29 :
30 : #include "config.h"
31 : #include <cassert> // for assert
32 : #include <cstdio> // for NULL, printf
33 : #include <stdint.h> // for int32_t, int8_t, int16_t, etc
34 : #include "mm/gc.hpp" // for GCCriticalSection, etc
35 : #include "threads/lockword.hpp" // for Lockword
36 : #include "vm/class.hpp" // for classinfo
37 : #include "vm/exceptions.hpp"
38 : #include "vm/global.hpp" // for java_handle_t, java_array_t, etc
39 : #include "vm/jit/builtin.hpp" // for builtin_canstore
40 : #include "vm/os.hpp" // for os
41 : #include "vm/primitive.hpp" // for primitivetypeinfo, etc
42 : #include "vm/types.hpp" // for s4, s2
43 : #include "vm/vftbl.hpp" // for vftbl_t
44 :
45 : /* array types ****************************************************************/
46 :
47 : /* CAUTION: Don't change the numerical values! These constants (with
48 : the exception of ARRAYTYPE_OBJECT) are used as indices in the
49 : primitive type table. */
50 :
51 : enum ArrayType {
52 : ARRAYTYPE_INT = PRIMITIVETYPE_INT,
53 : ARRAYTYPE_LONG = PRIMITIVETYPE_LONG,
54 : ARRAYTYPE_FLOAT = PRIMITIVETYPE_FLOAT,
55 : ARRAYTYPE_DOUBLE = PRIMITIVETYPE_DOUBLE,
56 : ARRAYTYPE_BYTE = PRIMITIVETYPE_BYTE,
57 : ARRAYTYPE_CHAR = PRIMITIVETYPE_CHAR,
58 : ARRAYTYPE_SHORT = PRIMITIVETYPE_SHORT,
59 : ARRAYTYPE_BOOLEAN = PRIMITIVETYPE_BOOLEAN,
60 : ARRAYTYPE_OBJECT = PRIMITIVETYPE_VOID // don't use as index!
61 : };
62 :
63 :
64 : /* arraydescriptor *************************************************************
65 :
66 : For every array class an arraydescriptor is allocated which
67 : describes the array class. The arraydescriptor is referenced from
68 : the vftbl of the array class.
69 :
70 : *******************************************************************************/
71 :
72 : struct arraydescriptor {
73 : vftbl_t *componentvftbl; /* vftbl of the component type, NULL for primit. */
74 : vftbl_t *elementvftbl; /* vftbl of the element type, NULL for primitive */
75 : ArrayType arraytype; /* ARRAYTYPE_* constant */
76 : ArrayType elementtype; /* ARRAYTYPE_* constant */
77 : s4 dataoffset; /* offset of the array data from object pointer */
78 : s4 componentsize; /* size of a component in bytes */
79 : s2 dimension; /* dimension of the array (always >= 1) */
80 : };
81 :
82 :
83 : /**
84 : * This is a generic accessor class for Java arrays (of unspecified type),
85 : * which can be used to safely operate on Java arrays in native code.
86 : */
87 271 : class Array {
88 : protected:
89 : // Handle of Java array.
90 : java_handle_array_t* _handle;
91 :
92 : private:
93 : // We don't want a Java arrays to be copied.
94 : Array(Array* a) {}
95 : Array(Array& a) {}
96 :
97 : public:
98 : Array(java_handle_t* h);
99 : Array(int32_t length, classinfo* arrayclass);
100 2621650 : virtual ~Array() {}
101 :
102 : // Getters.
103 22785919 : virtual java_handle_array_t* get_handle() const { return _handle; }
104 : int32_t get_length() const;
105 :
106 : // Null checks.
107 : bool is_null () const;
108 : bool is_non_null() const;
109 :
110 : // Safe element modification functions for primitive values
111 : imm_union get_primitive_element(int32_t index);
112 : void set_primitive_element(int32_t index, imm_union value);
113 :
114 : // Safe element modification functions for boxed values
115 : java_handle_t* get_boxed_element(int32_t index);
116 : void set_boxed_element(int32_t index, java_handle_t *o);
117 : };
118 :
119 :
120 : /**
121 : * Constructor checks if passed handle really is a Java array.
122 : */
123 1789653 : inline Array::Array(java_handle_t* h)
124 : {
125 1789653 : if (h == NULL) {
126 337653 : _handle = NULL;
127 337653 : return;
128 : }
129 :
130 : #if 0
131 : classinfo* c;
132 : LLNI_class_get(h, c);
133 : if (!class_is_array(c)) {
134 : printf("Array::Array(): WARNING, passed handle is not an array\n");
135 : //exceptions_throw_illegalargumentexception("Argument is not an array");
136 : exceptions_throw_illegalargumentexception();
137 : _handle = NULL;
138 : return;
139 : }
140 : #endif
141 :
142 1452000 : _handle = h;
143 : }
144 :
145 : /**
146 : * Creates an array of the given array type on the heap.
147 : * The handle pointer to the array can be NULL in case of an exception.
148 : */
149 832138 : inline Array::Array(int32_t size, classinfo* arrayclass)
150 : {
151 : // Sanity check.
152 832138 : assert(class_is_array(arrayclass));
153 :
154 832138 : if (size < 0) {
155 3 : exceptions_throw_negativearraysizeexception();
156 3 : _handle = NULL;
157 3 : return;
158 : }
159 :
160 832135 : arraydescriptor* desc = arrayclass->vftbl->arraydesc;
161 832135 : int32_t dataoffset = desc->dataoffset;
162 832135 : int32_t componentsize = desc->componentsize;
163 832135 : int32_t actualsize = dataoffset + size * componentsize;
164 :
165 : // Check for overflow.
166 :
167 832135 : if (((u4) actualsize) < ((u4) size)) {
168 0 : exceptions_throw_outofmemoryerror();
169 0 : _handle = NULL;
170 0 : return;
171 : }
172 :
173 832135 : java_array_t* a = (java_array_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
174 :
175 832135 : if (a == NULL) {
176 2 : _handle = NULL;
177 2 : return;
178 : }
179 :
180 832133 : LLNI_vftbl_direct(a) = arrayclass->vftbl;
181 :
182 832133 : Lockword(a->objheader.lockword).init();
183 :
184 832133 : a->size = size;
185 :
186 832133 : _handle = (java_handle_array_t*) a;
187 : }
188 :
189 8119109 : inline int32_t Array::get_length() const
190 : {
191 8119109 : if (is_null()) {
192 0 : printf("Array::get_length(): WARNING, got null-pointer\n");
193 0 : exceptions_throw_nullpointerexception();
194 0 : return -1;
195 : }
196 :
197 : // XXX Fix me!
198 8119109 : int32_t length = ((java_array_t*) _handle)->size;
199 :
200 8119109 : return length;
201 : }
202 :
203 15544912 : inline bool Array::is_null() const
204 : {
205 15544912 : return (_handle == NULL);
206 : }
207 :
208 271 : inline bool Array::is_non_null() const
209 : {
210 271 : return (_handle != NULL);
211 : }
212 :
213 :
214 : /**
215 : * This is a template of an accessor class for Java arrays
216 : * of a specific type.
217 : */
218 1316336 : template<class T> class ArrayTemplate : public Array {
219 : protected:
220 484574 : ArrayTemplate(int32_t length, classinfo* arrayclass) : Array(length, arrayclass) {}
221 :
222 : public:
223 831632 : ArrayTemplate(java_handle_array_t* h) : Array(h) {}
224 :
225 : // XXX This should be protected or private!
226 : virtual T* get_raw_data_ptr() = 0;
227 :
228 : // Safe element modification functions
229 : T get_element(int32_t index);
230 : void set_element(int32_t index, T value);
231 :
232 : // Region copy functions
233 : void get_region(int32_t offset, int32_t count, T* buffer);
234 : void set_region(int32_t offset, int32_t count, const T* buffer);
235 : };
236 :
237 :
238 12885 : template<class T> inline T ArrayTemplate<T>::get_element(int32_t index)
239 : {
240 12885 : if (is_null()) {
241 0 : exceptions_throw_nullpointerexception();
242 0 : return 0;
243 : }
244 :
245 12885 : if ((index < 0) || (index >= get_length())) {
246 0 : exceptions_throw_arrayindexoutofboundsexception();
247 0 : return 0;
248 : }
249 :
250 12885 : T* ptr = get_raw_data_ptr();
251 :
252 12885 : return ptr[index];
253 : }
254 :
255 686 : template<class T> inline void ArrayTemplate<T>::set_element(int32_t index, T value)
256 : {
257 686 : if (is_null()) {
258 0 : exceptions_throw_nullpointerexception();
259 0 : return;
260 : }
261 :
262 686 : if ((index < 0) || (index >= get_length())) {
263 0 : exceptions_throw_arrayindexoutofboundsexception();
264 0 : return;
265 : }
266 :
267 686 : T* ptr = get_raw_data_ptr();
268 :
269 686 : ptr[index] = value;
270 : }
271 :
272 7057689 : template<> inline void ArrayTemplate<java_handle_t*>::set_element(int32_t index, java_handle_t* value)
273 : {
274 7057689 : if (is_null()) {
275 0 : exceptions_throw_nullpointerexception();
276 0 : return;
277 : }
278 :
279 : // Sanity check.
280 7057689 : assert(((java_array_t*) get_handle())->objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT);
281 :
282 : // Check if value can be stored
283 7057689 : if (!builtin_canstore(get_handle(), value)) {
284 0 : exceptions_throw_illegalargumentexception();
285 0 : return;
286 : }
287 :
288 7057689 : if ((index < 0) || (index >= get_length())) {
289 0 : exceptions_throw_arrayindexoutofboundsexception();
290 0 : return;
291 : }
292 :
293 7057689 : java_handle_t** ptr = get_raw_data_ptr();
294 :
295 7057689 : ptr[index] = value;
296 : }
297 :
298 0 : template<class T> inline void ArrayTemplate<T>::get_region(int32_t offset, int32_t count, T* buffer)
299 : {
300 : // Copy the array region inside a GC critical section.
301 0 : GCCriticalSection cs;
302 :
303 0 : const T* ptr = get_raw_data_ptr();
304 :
305 0 : os::memcpy(buffer, ptr + offset, sizeof(T) * count);
306 0 : }
307 :
308 0 : template<class T> inline void ArrayTemplate<T>::set_region(int32_t offset, int32_t count, const T* buffer)
309 : {
310 : // Copy the array region inside a GC critical section.
311 0 : GCCriticalSection cs;
312 :
313 0 : T* ptr = get_raw_data_ptr();
314 :
315 0 : os::memcpy(ptr + offset, buffer, sizeof(T) * count);
316 0 : }
317 :
318 :
319 : /**
320 : * Actual implementations of common Java array access classes.
321 : */
322 0 : class BooleanArray : public ArrayTemplate<uint8_t> {
323 : public:
324 0 : BooleanArray(java_handle_booleanarray_t* h) : ArrayTemplate<uint8_t>(h) {}
325 0 : BooleanArray(int32_t length) : ArrayTemplate<uint8_t>(length, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass) {}
326 0 : uint8_t* get_raw_data_ptr() { return ((java_booleanarray_t*) get_handle())->data; }
327 : };
328 :
329 402529 : class ByteArray : public ArrayTemplate<int8_t> {
330 : public:
331 190522 : ByteArray(java_handle_bytearray_t* h) : ArrayTemplate<int8_t>(h) {}
332 212007 : ByteArray(int32_t length) : ArrayTemplate<int8_t>(length, primitivetype_table[ARRAYTYPE_BYTE].arrayclass) {}
333 211884 : int8_t* get_raw_data_ptr() { return (int8_t*) ((java_bytearray_t*) get_handle())->data; }
334 : };
335 :
336 562434 : class CharArray : public ArrayTemplate<uint16_t> {
337 : public:
338 294324 : CharArray(java_handle_chararray_t* h) : ArrayTemplate<uint16_t>(h) {}
339 268111 : CharArray(int32_t length) : ArrayTemplate<uint16_t>(length, primitivetype_table[ARRAYTYPE_CHAR].arrayclass) {}
340 229626 : uint16_t* get_raw_data_ptr() { return ((java_chararray_t*) get_handle())->data; }
341 : };
342 :
343 2540 : class ShortArray : public ArrayTemplate<int16_t> {
344 : public:
345 0 : ShortArray(java_handle_shortarray_t* h) : ArrayTemplate<int16_t>(h) {}
346 2540 : ShortArray(int32_t length) : ArrayTemplate<int16_t>(length, primitivetype_table[ARRAYTYPE_SHORT].arrayclass) {}
347 0 : int16_t* get_raw_data_ptr() { return ((java_shortarray_t*) get_handle())->data; }
348 : };
349 :
350 1852 : class IntArray : public ArrayTemplate<int32_t> {
351 : public:
352 2 : IntArray(java_handle_intarray_t* h) : ArrayTemplate<int32_t>(h) {}
353 1850 : IntArray(int32_t length) : ArrayTemplate<int32_t>(length, primitivetype_table[ARRAYTYPE_INT].arrayclass) {}
354 2 : int32_t* get_raw_data_ptr() { return ((java_intarray_t*) get_handle())->data; }
355 : };
356 :
357 50 : class LongArray : public ArrayTemplate<int64_t> {
358 : public:
359 2 : LongArray(java_handle_longarray_t* h) : ArrayTemplate<int64_t>(h) {}
360 48 : LongArray(int32_t length) : ArrayTemplate<int64_t>(length, primitivetype_table[ARRAYTYPE_LONG].arrayclass) {}
361 2 : int64_t* get_raw_data_ptr() { return ((java_longarray_t*) get_handle())->data; }
362 : };
363 :
364 9 : class FloatArray : public ArrayTemplate<float> {
365 : public:
366 0 : FloatArray(java_handle_floatarray_t* h) : ArrayTemplate<float>(h) {}
367 9 : FloatArray(int32_t length) : ArrayTemplate<float>(length, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass) {}
368 0 : float* get_raw_data_ptr() { return ((java_floatarray_t*) get_handle())->data; }
369 : };
370 :
371 9 : class DoubleArray : public ArrayTemplate<double> {
372 : public:
373 0 : DoubleArray(java_handle_doublearray_t* h) : ArrayTemplate<double>(h) {}
374 9 : DoubleArray(int32_t length) : ArrayTemplate<double>(length, primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass) {}
375 0 : double* get_raw_data_ptr() { return ((java_doublearray_t*) get_handle())->data; }
376 : };
377 :
378 : /**
379 : * Actual implementation of access class for Java Object arrays.
380 : */
381 345013 : class ObjectArray : public ArrayTemplate<java_handle_t*> {
382 : public:
383 32814 : ObjectArray(java_handle_objectarray_t* h) : ArrayTemplate<java_handle_t*>(h) {}
384 : ObjectArray(int32_t length, classinfo* componentclass);
385 7070748 : java_handle_t** get_raw_data_ptr() { return ((java_objectarray_t*) get_handle())->data; }
386 : };
387 :
388 : /**
389 : * Actual implementation of access class for java.lang.Class arrays.
390 : */
391 1899 : class ClassArray : public ArrayTemplate<classinfo*> {
392 : public:
393 : ClassArray(int32_t length);
394 686 : classinfo** get_raw_data_ptr() { return (classinfo**) ((java_objectarray_t*) get_handle())->data; }
395 : };
396 :
397 : #endif // ARRAY_HPP_
398 :
399 :
400 : /*
401 : * These are local overrides for various environment variables in Emacs.
402 : * Please do not remove this and leave it at the end of the file, where
403 : * Emacs will automagically detect them.
404 : * ---------------------------------------------------------------------
405 : * Local variables:
406 : * mode: c++
407 : * indent-tabs-mode: t
408 : * c-basic-offset: 4
409 : * tab-width: 4
410 : * End:
411 : * vim:noexpandtab:sw=4:ts=4:
412 : */
|