* src/vm/jit/arm/codegen.c: Remove hack for return value in float registers.
[cacao.git] / src / vm / array.cpp
1 /* src/vm/array.cpp - 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 #include "config.h"
28
29 #include <stdint.h>
30
31 #include "native/llni.h"
32
33 #include "vm/array.hpp"
34 #include "vm/exceptions.hpp"
35 #include "vm/global.h"
36 #include "vm/globals.hpp"
37 #include "vm/primitive.hpp"
38 #include "vm/vm.hpp"
39
40
41 /**
42  * Returns a boxed element of the given Java array.
43  */
44 java_handle_t* Array::get_boxed_element(int32_t index)
45 {
46         vftbl_t       *v;
47         int            type;
48         imm_union      value;
49         java_handle_t *o;
50
51         if (is_null()) {
52                 exceptions_throw_nullpointerexception();
53                 return NULL;
54         }
55
56         v = LLNI_vftbl_direct(_handle);
57
58         type = v->arraydesc->arraytype;
59
60         value = get_primitive_element(index);
61
62         o = Primitive::box(type, value);
63
64         return o;
65 }
66
67
68 /**
69  * Sets a boxed element in the given Java array.
70  */
71 void Array::set_boxed_element(int32_t index, java_handle_t *o)
72 {
73         vftbl_t  *v;
74         int       type;
75         imm_union value;
76
77         if (is_null()) {
78                 exceptions_throw_nullpointerexception();
79                 return;
80         }
81
82         v = LLNI_vftbl_direct(_handle);
83
84         type = v->arraydesc->arraytype;
85
86         // Special handling for object arrays.
87         if (type == ARRAYTYPE_OBJECT) {
88                 ObjectArray array(_handle);
89                 array.set_element(index, o);
90                 return;
91         }
92
93         // Check if primitive type can be stored.
94         if (!Primitive::unbox_typed(o, type, &value)) {
95 /*              exceptions_throw_illegalargumentexception("argument type mismatch"); */
96                 exceptions_throw_illegalargumentexception();
97                 return;
98         }
99
100         set_primitive_element(index, value);
101 }
102
103
104 /**
105  * Returns a primitive element of the given Java array.
106  */
107 imm_union Array::get_primitive_element(int32_t index)
108 {
109         vftbl_t  *v;
110         int       type;
111         imm_union value;
112
113         if (is_null()) {
114                 exceptions_throw_nullpointerexception();
115                 value.a = NULL;
116                 return value;
117         }
118
119         java_handle_array_t* a = _handle;
120
121         v = LLNI_vftbl_direct(a);
122
123         type = v->arraydesc->arraytype;
124
125         switch (type) {
126         case ARRAYTYPE_BOOLEAN:
127                 {
128                         BooleanArray array(a);
129                         value.i = array.get_element(index);
130                 }
131                 break;
132         case ARRAYTYPE_BYTE:
133                 {
134                         ByteArray array(a);
135                         value.i = array.get_element(index);
136                 }
137                 break;
138         case ARRAYTYPE_CHAR:
139                 {
140                         CharArray array(a);
141                         value.i = array.get_element(index);
142                 }
143                 break;
144         case ARRAYTYPE_SHORT:
145                 {
146                         ShortArray array(a);
147                         value.i = array.get_element(index);
148                 }
149                 break;
150         case ARRAYTYPE_INT:
151                 {
152                         IntArray array(a);
153                         value.i = array.get_element(index);
154                 }
155                 break;
156         case ARRAYTYPE_LONG:
157                 {
158                         LongArray array(a);
159                         value.l = array.get_element(index);
160                 }
161                 break;
162         case ARRAYTYPE_FLOAT:
163                 {
164                         FloatArray array(a);
165                         value.f = array.get_element(index);
166                 }
167                 break;
168         case ARRAYTYPE_DOUBLE:
169                 {
170                         DoubleArray array(a);
171                         value.d = array.get_element(index);
172                 }
173                 break;
174         case ARRAYTYPE_OBJECT:
175                 {
176                         ObjectArray array(a);
177                         value.a = array.get_element(index);
178                 }
179                 break;
180         default:
181                 vm_abort("Array::primitive_element_get: invalid array element type %d",
182                                  type);
183         }
184
185         return value;
186 }
187
188
189 /**
190  * Sets a primitive element in the given Java array.
191  */
192 void Array::set_primitive_element(int32_t index, imm_union value)
193 {
194         vftbl_t *v;
195         int      type;
196
197         if (is_null()) {
198                 exceptions_throw_nullpointerexception();
199                 return;
200         }
201
202         java_handle_array_t* a = _handle;
203
204         v = LLNI_vftbl_direct(a);
205
206         type = v->arraydesc->arraytype;
207
208         switch (type) {
209         case ARRAYTYPE_BOOLEAN:
210                 {
211                         BooleanArray array(a);
212                         array.set_element(index, value.i);
213                 }
214                 break;
215         case ARRAYTYPE_BYTE:
216                 {
217                         ByteArray array(a);
218                         array.set_element(index, value.i);
219                 }
220                 break;
221         case ARRAYTYPE_CHAR:
222                 {
223                         CharArray array(a);
224                         array.set_element(index, value.i);
225                 }
226                 break;
227         case ARRAYTYPE_SHORT:
228                 {
229                         ShortArray array(a);
230                         array.set_element(index, value.i);
231                 }
232                 break;
233         case ARRAYTYPE_INT:
234                 {
235                         IntArray array(a);
236                         array.set_element(index, value.i);
237                 }
238                 break;
239         case ARRAYTYPE_LONG:
240                 {
241                         LongArray array(a);
242                         array.set_element(index, value.l);
243                 }
244                 break;
245         case ARRAYTYPE_FLOAT:
246                 {
247                         FloatArray array(a);
248                         array.set_element(index, value.f);
249                 }
250                 break;
251         case ARRAYTYPE_DOUBLE:
252                 {
253                         DoubleArray array(a);
254                         array.set_element(index, value.d);
255                 }
256                 break;
257         case ARRAYTYPE_OBJECT:
258                 {
259                         ObjectArray array(a);
260                         array.set_element(index, static_cast<java_handle_t*>(value.a));
261                 }
262                 break;
263         default:
264                 vm_abort("array_element_primitive_set: invalid array element type %d",
265                                  type);
266         }
267 }
268
269
270 /**
271  * Creates an array of references to the given class type on the heap.
272  * The handle pointer to the array can be NULL in case of an exception.
273  */
274 ObjectArray::ObjectArray(int32_t length, classinfo* componentclass)
275                 : ArrayTemplate<java_handle_t*>(NULL)
276 {
277         // Is class loaded?
278         assert(componentclass->state & CLASS_LOADED);
279
280         // Is class linked?
281         if (!(componentclass->state & CLASS_LINKED))
282                 if (!link_class(componentclass)) {
283                         _handle = NULL;
284                         return;
285                 }
286
287         classinfo* arrayclass = class_array_of(componentclass, true);
288
289         if (arrayclass == NULL) {
290                 _handle = NULL;
291                 return;
292         }
293
294         // Delegate allocation to generic array class
295         Array a(length, arrayclass);
296
297         _handle = a.get_handle();
298 }
299
300
301 /**
302  * Creates an array of references to classinfos on the heap.
303  * The handle pointer to the array can be NULL in case of an exception.
304  */
305 ClassArray::ClassArray(int32_t length)
306                 : ArrayTemplate<classinfo*>(NULL)
307 {
308         // Delegate allocation to object array class
309         ObjectArray oa(length, class_java_lang_Class);
310
311         _handle = oa.get_handle();
312 }
313
314
315 /*
316  * These are local overrides for various environment variables in Emacs.
317  * Please do not remove this and leave it at the end of the file, where
318  * Emacs will automagically detect them.
319  * ---------------------------------------------------------------------
320  * Local variables:
321  * mode: c++
322  * indent-tabs-mode: t
323  * c-basic-offset: 4
324  * tab-width: 4
325  * End:
326  * vim:noexpandtab:sw=4:ts=4:
327  */