This commit introduces C++ wrapper classes for Java heap objects.
[cacao.git] / src / vm / primitive.cpp
1 /* src/vm/primitive.cpp - primitive types
2
3    Copyright (C) 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30
31 #include "native/jni.h"
32 #include "native/llni.h"
33
34 #include "vm/builtin.h"
35 #include "vm/global.h"
36 #include "vm/primitive.hpp"
37 #include "vm/vm.hpp"
38
39 #include "vmcore/class.h"
40 #include "vmcore/globals.hpp"
41 #include "vmcore/javaobjects.hpp"
42 #include "vmcore/utf8.h"
43
44
45 /**
46  * Returns the primitive class of the given class name.
47  *
48  * @param name Name of the class.
49  *
50  * @return Class structure.
51  */
52 classinfo* Primitive::get_class_by_name(utf *name)
53 {
54         int i;
55
56         /* search table of primitive classes */
57
58         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
59                 if (primitivetype_table[i].name == name)
60                         return primitivetype_table[i].class_primitive;
61
62         /* keep compiler happy */
63
64         return NULL;
65 }
66
67
68 /**
69  * Returns the primitive class of the given type.
70  *
71  * @param type Integer type of the class.
72  *
73  * @return Class structure.
74  */
75 classinfo* Primitive::get_class_by_type(int type)
76 {
77         return primitivetype_table[type].class_primitive;
78 }
79
80
81 /**
82  * Returns the primitive class of the given type.
83  *
84  * @param ch 
85  *
86  * @return Class structure.
87  */
88 classinfo* Primitive::get_class_by_char(char ch)
89 {
90         int index;
91
92         switch (ch) {
93         case 'I':
94                 index = PRIMITIVETYPE_INT;
95                 break;
96         case 'J':
97                 index = PRIMITIVETYPE_LONG;
98                 break;
99         case 'F':
100                 index = PRIMITIVETYPE_FLOAT;
101                 break;
102         case 'D':
103                 index = PRIMITIVETYPE_DOUBLE;
104                 break;
105         case 'B':
106                 index = PRIMITIVETYPE_BYTE;
107                 break;
108         case 'C':
109                 index = PRIMITIVETYPE_CHAR;
110                 break;
111         case 'S':
112                 index = PRIMITIVETYPE_SHORT;
113                 break;
114         case 'Z':
115                 index = PRIMITIVETYPE_BOOLEAN;
116                 break;
117         case 'V':
118                 index = PRIMITIVETYPE_VOID;
119                 break;
120         default:
121                 return NULL;
122         }
123
124         return primitivetype_table[index].class_primitive;
125 }
126
127
128 /**
129  * Returns the primitive array-class of the given primitive class
130  * name.
131  *
132  * @param name Name of the class.
133  *
134  * @return Class structure.
135  */
136 classinfo* Primitive::get_arrayclass_by_name(utf *name)
137 {
138         int i;
139
140         /* search table of primitive classes */
141
142         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
143                 if (primitivetype_table[i].name == name)
144                         return primitivetype_table[i].arrayclass;
145
146         /* keep compiler happy */
147
148         return NULL;
149 }
150
151
152 /**
153  * Returns the primitive array-class of the given type.
154  *
155  * @param type Integer type of the class.
156  *
157  * @return Class structure.
158  */
159 classinfo* Primitive::get_arrayclass_by_type(int type)
160 {
161         return primitivetype_table[type].arrayclass;
162 }
163
164
165 /**
166  * Returns the primitive type of the given wrapper-class.
167  *
168  * @param c Class structure.
169  *
170  * @return Integer type of the class.
171  */
172 int Primitive::get_type_by_wrapperclass(classinfo *c)
173 {
174         int i;
175
176         /* Search primitive table. */
177
178         for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
179                 if (primitivetype_table[i].class_wrap == c)
180                         return i;
181
182         /* Invalid primitive wrapper-class. */
183
184         return -1;
185 }
186
187
188 /**
189  * Box a primitive of the given type.  If the type is an object,
190  * simply return it.
191  *
192  * @param type  Type of the passed value.
193  * @param value Value to box.
194  *
195  * @return Handle of the boxing Java object.
196  */
197 java_handle_t* Primitive::box(int type, imm_union value)
198 {
199         java_handle_t* o;
200
201         switch (type) {
202         case PRIMITIVETYPE_BOOLEAN:
203                 o = box((uint8_t) value.i);
204                 break;
205         case PRIMITIVETYPE_BYTE:
206                 o = box((int8_t) value.i);
207                 break;
208         case PRIMITIVETYPE_CHAR:
209                 o = box((uint16_t) value.i);
210                 break;
211         case PRIMITIVETYPE_SHORT:
212                 o = box((int16_t) value.i);
213                 break;
214         case PRIMITIVETYPE_INT:
215                 o = box(value.i);
216                 break;
217         case PRIMITIVETYPE_LONG:
218                 o = box(value.l);
219                 break;
220         case PRIMITIVETYPE_FLOAT:
221                 o = box(value.f);
222                 break;
223         case PRIMITIVETYPE_DOUBLE:
224                 o = box(value.d);
225                 break;
226         case PRIMITIVETYPE_VOID:
227                 o = (java_handle_t*) value.a;
228                 break;
229         default:
230                 o = NULL;
231                 vm_abort("primitive_box: invalid primitive type %d", type);
232         }
233
234         return o;
235 }
236
237
238 /**
239  * Unbox a primitive of the given type.  If the type is an object,
240  * simply return it.
241  *
242  * @param h Handle of the Java object.
243  *
244  * @return Unboxed value as union.
245  */
246 imm_union Primitive::unbox(java_handle_t *h)
247 {
248         classinfo *c;
249         int        type;
250         imm_union  value;
251
252         if (h == NULL) {
253                 value.a = NULL;
254                 return value;
255         }
256
257         LLNI_class_get(h, c);
258
259         type = get_type_by_wrapperclass(c);
260
261         switch (type) {
262         case PRIMITIVETYPE_BOOLEAN:
263                 value.i = unbox_boolean(h);
264                 break;
265         case PRIMITIVETYPE_BYTE:
266                 value.i = unbox_byte(h);
267                 break;
268         case PRIMITIVETYPE_CHAR:
269                 value.i = unbox_char(h);
270                 break;
271         case PRIMITIVETYPE_SHORT:
272                 value.i = unbox_short(h);
273                 break;
274         case PRIMITIVETYPE_INT:
275                 value.i = unbox_int(h);
276                 break;
277         case PRIMITIVETYPE_LONG:
278                 value.l = unbox_long(h);
279                 break;
280         case PRIMITIVETYPE_FLOAT:
281                 value.f = unbox_float(h);
282                 break;
283         case PRIMITIVETYPE_DOUBLE:
284                 value.d = unbox_double(h);
285                 break;
286         case -1:
287                 /* If type is -1 the object is not a primitive box but a
288                    normal object. */
289                 value.a = h;
290                 break;
291         default:
292                 vm_abort("Primitive::unbox: invalid primitive type %d", type);
293         }
294
295         return value;
296 }
297
298
299 /**
300  * Box a primitive type.
301  */
302 java_handle_t* Primitive::box(uint8_t value)
303 {
304         java_handle_t *h = builtin_new(class_java_lang_Boolean);
305
306         if (h == NULL)
307                 return NULL;
308
309         java_lang_Boolean b(h);
310         b.set_value(value);
311
312         return h;
313 }
314
315 java_handle_t* Primitive::box(int8_t value)
316 {
317         java_handle_t *h = builtin_new(class_java_lang_Byte);
318
319         if (h == NULL)
320                 return NULL;
321
322         java_lang_Byte b(h);
323         b.set_value(value);
324
325         return h;
326 }
327
328 java_handle_t* Primitive::box(uint16_t value)
329 {
330         java_handle_t *h = builtin_new(class_java_lang_Character);
331
332         if (h == NULL)
333                 return NULL;
334
335         java_lang_Character c(h);
336         c.set_value(value);
337
338         return h;
339 }
340
341 java_handle_t* Primitive::box(int16_t value)
342 {
343         java_handle_t *h = builtin_new(class_java_lang_Short);
344
345         if (h == NULL)
346                 return NULL;
347
348         java_lang_Short s(h);
349         s.set_value(value);
350
351         return h;
352 }
353
354 java_handle_t* Primitive::box(int32_t value)
355 {
356         java_handle_t *h = builtin_new(class_java_lang_Integer);
357
358         if (h == NULL)
359                 return NULL;
360
361         java_lang_Integer i(h);
362         i.set_value(value);
363
364         return h;
365 }
366
367 java_handle_t* Primitive::box(int64_t value)
368 {
369         java_handle_t *h = builtin_new(class_java_lang_Long);
370
371         if (h == NULL)
372                 return NULL;
373
374         java_lang_Long l(h);
375         l.set_value(value);
376
377         return h;
378 }
379
380 java_handle_t* Primitive::box(float value)
381 {
382         java_handle_t *h = builtin_new(class_java_lang_Float);
383
384         if (h == NULL)
385                 return NULL;
386
387         java_lang_Float f(h);
388         f.set_value(value);
389
390         return h;
391 }
392
393 java_handle_t* Primitive::box(double value)
394 {
395         java_handle_t *h = builtin_new(class_java_lang_Double);
396
397         if (h == NULL)
398                 return NULL;
399
400         java_lang_Double d(h);
401         d.set_value(value);
402
403         return h;
404 }
405
406
407
408 /**
409  * Unbox a primitive type.
410  */
411
412 // template<class T> T Primitive::unbox(java_handle_t *h)
413 // {
414 //      return java_lang_Boolean::get_value(h);
415 // }
416
417 inline uint8_t Primitive::unbox_boolean(java_handle_t *h)
418 {
419         java_lang_Boolean b(h);
420         return b.get_value();
421 }
422
423 inline int8_t Primitive::unbox_byte(java_handle_t *h)
424 {
425         java_lang_Byte b(h);
426         return b.get_value();
427 }
428
429 inline uint16_t Primitive::unbox_char(java_handle_t *h)
430 {
431         java_lang_Character c(h);
432         return c.get_value();
433 }
434
435 inline int16_t Primitive::unbox_short(java_handle_t *h)
436 {
437         java_lang_Short s(h);
438         return s.get_value();
439 }
440
441 inline int32_t Primitive::unbox_int(java_handle_t *h)
442 {
443         java_lang_Integer i(h);
444         return i.get_value();
445 }
446
447 inline int64_t Primitive::unbox_long(java_handle_t *h)
448 {
449         java_lang_Long l(h);
450         return l.get_value();
451 }
452
453 inline float Primitive::unbox_float(java_handle_t *h)
454 {
455         java_lang_Float f(h);
456         return f.get_value();
457 }
458
459 inline double Primitive::unbox_double(java_handle_t *h)
460 {
461         java_lang_Double d(h);
462         return d.get_value();
463 }
464
465
466
467 // Legacy C interface.
468
469 extern "C" {
470
471         classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
472 classinfo* Primitive_get_class_by_type(int type) { return Primitive::get_class_by_type(type); }
473 classinfo* Primitive_get_class_by_char(char ch) { return Primitive::get_class_by_char(ch); }
474 classinfo* Primitive_get_arrayclass_by_name(utf *name) { return Primitive::get_arrayclass_by_name(name); }
475 classinfo* Primitive_get_arrayclass_by_type(int type) { return Primitive::get_arrayclass_by_type(type); }
476 int Primitive_get_type_by_wrapperclass(classinfo *c) { return Primitive::get_type_by_wrapperclass(c); }
477 java_handle_t* Primitive_box(int type, imm_union value) { return Primitive::box(type, value); }
478 imm_union Primitive_unbox(java_handle_t *h) { return Primitive::unbox(h); }
479 }
480
481
482 /*
483  * These are local overrides for various environment variables in Emacs.
484  * Please do not remove this and leave it at the end of the file, where
485  * Emacs will automagically detect them.
486  * ---------------------------------------------------------------------
487  * Local variables:
488  * mode: c++
489  * indent-tabs-mode: t
490  * c-basic-offset: 4
491  * tab-width: 4
492  * End:
493  * vim:noexpandtab:sw=4:ts=4:
494  */