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