PR140 - repaired icedtea7
[cacao.git] / src / vm / field.cpp
1 /* src/vm/field.cpp - field functions
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008, 2010
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 #include <stdio.h>
31
32 #include "mm/memory.hpp"
33
34 #include "native/llni.h"
35
36 #include "vm/types.h"
37
38 #include "vm/annotation.hpp"
39 #include "vm/array.hpp"
40 #include "vm/jit/builtin.hpp"
41 #include "vm/class.hpp"
42 #include "vm/descriptor.hpp"
43 #include "vm/exceptions.hpp"
44 #include "vm/field.hpp"
45 #include "vm/global.h"
46 #include "vm/globals.hpp"
47 #include "vm/loader.hpp"
48 #include "vm/options.h"
49 #include "vm/primitive.hpp"
50 #include "vm/references.h"
51 #include "vm/string.hpp"
52 #include "vm/suck.hpp"
53 #include "vm/utf8.h"
54 #include "vm/vm.hpp"
55
56
57 /* field_load ******************************************************************
58
59    Load everything about a class field from the class file and fill a
60    fieldinfo structure.
61
62 *******************************************************************************/
63
64 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
65
66 bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
67 {
68         classinfo *c;
69         u4 attrnum, i;
70         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
71         utf *u;
72
73         /* Get class. */
74
75         c = cb->clazz;
76
77         f->clazz = c;
78
79         /* Get access flags. */
80
81         if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
82                 return false;
83
84         f->flags = suck_u2(cb);
85
86         /* Get name. */
87
88         if (!(u = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
89                 return false;
90
91         f->name = u;
92
93         /* Get descriptor. */
94
95         if (!(u = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
96                 return false;
97
98         f->descriptor = u;
99         f->parseddesc = NULL;
100
101         if (!descriptor_pool_add(descpool, u, NULL))
102                 return false;
103
104         /* descriptor_pool_add accepts method descriptors, so we have to
105            check against them here before the call of
106            descriptor_to_basic_type below. */
107
108         if (u->text[0] == '(') {
109                 exceptions_throw_classformaterror(c, "Method descriptor used for field");
110                 return false;
111         }
112
113 #ifdef ENABLE_VERIFIER
114         if (opt_verify) {
115                 /* check name */
116                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
117                         exceptions_throw_classformaterror(c,
118                                                                                           "Illegal Field name \"%s\"",
119                                                                                           f->name->text);
120                         return false;
121                 }
122
123                 /* check flag consistency */
124                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
125
126                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
127                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
128                         exceptions_throw_classformaterror(c,
129                                                                                           "Illegal field modifiers: 0x%X",
130                                                                                           f->flags);
131                         return false;
132                 }
133
134                 if (c->flags & ACC_INTERFACE) {
135                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
136                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
137                                 f->flags & ACC_TRANSIENT) {
138                                 exceptions_throw_classformaterror(c,
139                                                                                                   "Illegal field modifiers: 0x%X",
140                                                                                                   f->flags);
141                                 return false;
142                         }
143                 }
144         }
145 #endif /* ENABLE_VERIFIER */
146
147         /* data type */
148
149         f->type = descriptor_to_basic_type(f->descriptor);
150
151         /* For static-fields allocate memory for the value and set the
152            value to 0. */
153
154         if (f->flags & ACC_STATIC) {
155                 switch (f->type) {
156                 case TYPE_INT:
157                 case TYPE_LNG:
158                 case TYPE_FLT:
159                 case TYPE_DBL:
160                         f->value = NEW(imm_union);
161                         break;
162
163                 case TYPE_ADR:
164 #if !defined(ENABLE_GC_BOEHM)
165                         f->value = NEW(imm_union);
166 #else
167                         f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
168 #endif
169                         break;
170
171                 default:
172                         vm_abort("field_load: invalid field type %d", f->type);
173                 }
174
175                 /* Set the field to zero, for float and double fields set the
176                    correct 0.0 value. */
177
178                 switch (f->type) {
179                 case TYPE_INT:
180                 case TYPE_LNG:
181                 case TYPE_ADR:
182                         f->value->l = 0;
183                         break;
184
185                 case TYPE_FLT:
186                         f->value->f = 0.0;
187                         break;
188
189                 case TYPE_DBL:
190                         f->value->d = 0.0;
191                         break;
192                 }
193         }
194         else {
195                 /* For instance-fields set the offset to 0. */
196
197                 f->offset = 0;
198
199                 /* For final fields, which are not static, we need a value
200                    structure. */
201
202                 if (f->flags & ACC_FINAL) {
203                         f->value = NEW(imm_union);
204                         /* XXX hack */
205                         f->value->l = 0;
206                 }
207
208                 switch (f->type) {
209                 case TYPE_ADR:
210                         c->flags |= ACC_CLASS_HAS_POINTERS;
211                         break;
212                 }
213         }
214
215         /* read attributes */
216
217         if (!suck_check_classbuffer_size(cb, 2))
218                 return false;
219
220         attrnum = suck_u2(cb);
221
222         for (i = 0; i < attrnum; i++) {
223                 if (!suck_check_classbuffer_size(cb, 2))
224                         return false;
225
226                 if (!(u = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
227                         return false;
228
229                 if (u == utf_ConstantValue) {
230                         if (!suck_check_classbuffer_size(cb, 4 + 2))
231                                 return false;
232
233                         /* check attribute length */
234
235                         if (suck_u4(cb) != 2) {
236                                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
237                                 return false;
238                         }
239
240                         /* constant value attribute */
241
242                         if (pindex != field_load_NOVALUE) {
243                                 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
244                                 return false;
245                         }
246
247                         /* index of value in constantpool */
248
249                         pindex = suck_u2(cb);
250
251                         /* initialize field with value from constantpool */
252
253                         switch (f->type) {
254                         case TYPE_INT: {
255                                 constant_integer *ci; 
256
257                                 if (!(ci = (constant_integer*) class_getconstant(c, pindex, CONSTANT_Integer)))
258                                         return false;
259
260                                 f->value->i = ci->value;
261                         }
262                         break;
263
264                         case TYPE_LNG: {
265                                 constant_long *cl; 
266
267                                 if (!(cl = (constant_long*) class_getconstant(c, pindex, CONSTANT_Long)))
268                                         return false;
269
270                                 f->value->l = cl->value;
271                         }
272                         break;
273
274                         case TYPE_FLT: {
275                                 constant_float *cf;
276
277                                 if (!(cf = (constant_float*) class_getconstant(c, pindex, CONSTANT_Float)))
278                                         return false;
279
280                                 f->value->f = cf->value;
281                         }
282                         break;
283
284                         case TYPE_DBL: {
285                                 constant_double *cd;
286
287                                 if (!(cd = (constant_double*) class_getconstant(c, pindex, CONSTANT_Double)))
288                                         return false;
289
290                                 f->value->d = cd->value;
291                         }
292                         break;
293
294                         case TYPE_ADR:
295                                 if (!(u = (utf*) class_getconstant(c, pindex, CONSTANT_String)))
296                                         return false;
297
298                                 /* Create Java-string from compressed UTF8-string. */
299
300                                 if (!(class_java_lang_String->flags & CLASS_LINKED))
301                                         linker_create_string_later(reinterpret_cast<java_object_t**>(&f->value->a), u);
302                                 else
303                                         f->value->a = literalstring_new(u);
304                                 break;
305
306                         default: 
307                                 vm_abort("field_load: invalid field type %d", f->type);
308                         }
309                 }
310 #if defined(ENABLE_JAVASE)
311                 else if (u == utf_Signature) {
312                         /* Signature */
313
314                         if (!loader_load_attribute_signature(cb, &(f->signature)))
315                                 return false;
316                 }
317
318 #if defined(ENABLE_ANNOTATIONS)
319                 else if (u == utf_RuntimeVisibleAnnotations) {
320                         /* RuntimeVisibleAnnotations */
321                         if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
322                                 return false;
323                 }
324                 else if (u == utf_RuntimeInvisibleAnnotations) {
325                         /* RuntimeInvisibleAnnotations */
326                         if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
327                                 return false;
328                 }
329 #endif
330 #endif
331                 else {
332                         /* unknown attribute */
333
334                         if (!loader_skip_attribute_body(cb))
335                                 return false;
336                 }
337         }
338
339         /* everything was ok */
340
341         return true;
342 }
343
344
345 /* field_get_type **************************************************************
346
347    Returns the type of the field as class.
348
349 *******************************************************************************/
350
351 classinfo *field_get_type(fieldinfo *f)
352 {
353         typedesc  *td;
354         utf       *u;
355         classinfo *c;
356
357         td = f->parseddesc;
358
359         if (td->type == TYPE_ADR) {
360                 assert(td->classref);
361
362                 u = td->classref->name;
363
364                 /* load the class of the field-type with the field's
365                    classloader */
366
367                 c = load_class_from_classloader(u, f->clazz->classloader);
368         }
369         else {
370                 c = Primitive::get_class_by_type(td->primitivetype);
371         }
372
373         return c;
374 }
375
376
377 /* field_free ******************************************************************
378
379    Frees a fields' resources.
380
381 *******************************************************************************/
382
383 void field_free(fieldinfo *f)
384 {
385         /* free memory for fields which have a value */
386
387         if (f->value)
388 #if defined(ENABLE_GC_BOEHM)
389                 if (f->type != TYPE_ADR)
390 #endif
391                         FREE(f->value, imm_union);
392 }
393
394
395 /* field_get_annotations ******************************************************
396
397    Get a fields' unparsed annotations in a byte array.
398
399    IN:
400        f........the field of which the annotations should be returned
401
402    RETURN VALUE:
403        The unparsed annotations in a byte array (or NULL if there aren't any).
404
405 *******************************************************************************/
406
407 java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
408 {
409 #if defined(ENABLE_ANNOTATIONS)
410         classinfo               *c;           /* declaring class           */
411         int                      slot;        /* slot of this field        */
412         java_handle_t           *field_annotations;  /* array of unparsed  */
413                        /* annotations of all fields of the declaring class */
414
415         c    = f->clazz;
416         slot = f - c->fields;
417
418         LLNI_classinfo_field_get(c, field_annotations, field_annotations);
419
420         ObjectArray oa(field_annotations);
421
422         /* the field_annotations array might be shorter then the field
423          * count if the fields above a certain index have no annotations.
424          */
425         if (field_annotations != NULL && oa.get_length() > slot) {
426                 return (java_handle_bytearray_t*) oa.get_element(slot);
427         } else {
428                 return NULL;
429         }
430 #else
431         return NULL;
432 #endif
433 }
434
435
436 /* field_printflags ************************************************************
437
438    (debugging only)
439
440 *******************************************************************************/
441
442 #if !defined(NDEBUG)
443 void field_printflags(fieldinfo *f)
444 {
445         if (f == NULL) {
446                 printf("NULL");
447                 return;
448         }
449
450         if (f->flags & ACC_PUBLIC)       printf(" PUBLIC");
451         if (f->flags & ACC_PRIVATE)      printf(" PRIVATE");
452         if (f->flags & ACC_PROTECTED)    printf(" PROTECTED");
453         if (f->flags & ACC_STATIC)       printf(" STATIC");
454         if (f->flags & ACC_FINAL)        printf(" FINAL");
455         if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
456         if (f->flags & ACC_VOLATILE)     printf(" VOLATILE");
457         if (f->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
458         if (f->flags & ACC_NATIVE)       printf(" NATIVE");
459         if (f->flags & ACC_INTERFACE)    printf(" INTERFACE");
460         if (f->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
461 }
462 #endif
463
464
465 /* field_print *****************************************************************
466
467    (debugging only)
468
469 *******************************************************************************/
470
471 #if !defined(NDEBUG)
472 void field_print(fieldinfo *f)
473 {
474         if (f == NULL) {
475                 printf("(fieldinfo*)NULL");
476                 return;
477         }
478
479         utf_display_printable_ascii_classname(f->clazz->name);
480         printf(".");
481         utf_display_printable_ascii(f->name);
482         printf(" ");
483         utf_display_printable_ascii(f->descriptor);     
484
485         field_printflags(f);
486
487         if (!(f->flags & ACC_STATIC)) {
488                 printf(", offset: %d", f->offset);
489         }
490 }
491 #endif
492
493
494 /* field_println ***************************************************************
495
496    (debugging only)
497
498 *******************************************************************************/
499
500 #if !defined(NDEBUG)
501 void field_println(fieldinfo *f)
502 {
503         field_print(f);
504         printf("\n");
505 }
506 #endif
507
508 /* field_fieldref_print ********************************************************
509
510    (debugging only)
511
512 *******************************************************************************/
513
514 #if !defined(NDEBUG)
515 void field_fieldref_print(constant_FMIref *fr)
516 {
517         if (fr == NULL) {
518                 printf("(constant_FMIref *)NULL");
519                 return;
520         }
521
522         if (IS_FMIREF_RESOLVED(fr)) {
523                 printf("<field> ");
524                 field_print(fr->p.field);
525         }
526         else {
527                 printf("<fieldref> ");
528                 utf_display_printable_ascii_classname(fr->p.classref->name);
529                 printf(".");
530                 utf_display_printable_ascii(fr->name);
531                 printf(" ");
532                 utf_display_printable_ascii(fr->descriptor);
533         }
534 }
535 #endif
536
537 /* field_fieldref_println ******************************************************
538
539    (debugging only)
540
541 *******************************************************************************/
542
543 #if !defined(NDEBUG)
544 void field_fieldref_println(constant_FMIref *fr)
545 {
546         field_fieldref_print(fr);
547         printf("\n");
548 }
549 #endif
550
551 /*
552  * These are local overrides for various environment variables in Emacs.
553  * Please do not remove this and leave it at the end of the file, where
554  * Emacs will automagically detect them.
555  * ---------------------------------------------------------------------
556  * Local variables:
557  * mode: c
558  * indent-tabs-mode: t
559  * c-basic-offset: 4
560  * tab-width: 4
561  * End:
562  * vim:noexpandtab:sw=4:ts=4:
563  */