570c6958507f58e3d3ddbe9522a6c9dd71602dd9
[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    $Id: field.c 8343 2007-08-17 21:39:32Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <stdio.h>
35
36 #include "mm/memory.h"
37
38 #include "vm/types.h"
39
40 #include "mm/memory.h"
41
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/global.h"
45 #include "vm/primitive.h"
46 #include "vm/stringlocal.h"
47 #include "vm/vm.h"
48
49 #include "vmcore/annotation.h"
50 #include "vmcore/class.h"
51 #include "vmcore/descriptor.h"
52 #include "vmcore/field.h"
53 #include "vmcore/loader.h"
54 #include "vmcore/options.h"
55 #include "vmcore/references.h"
56 #include "vmcore/suck.h"
57 #include "vmcore/utf8.h"
58
59
60 /* field_load ******************************************************************
61
62    Load everything about a class field from the class file and fill a
63    fieldinfo structure.
64
65 *******************************************************************************/
66
67 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
68
69 bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
70 {
71         classinfo *c;
72         u4 attrnum, i;
73         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
74         utf *u;
75
76         /* Get class. */
77
78         c = cb->class;
79
80         f->class = c;
81
82         /* Get access flags. */
83
84         if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
85                 return false;
86
87         f->flags = suck_u2(cb);
88
89         /* Get name. */
90
91         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
92                 return false;
93
94         f->name = u;
95
96         /* Get descriptor. */
97
98         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
99                 return false;
100
101         f->descriptor = u;
102         f->parseddesc = NULL;
103
104         if (!descriptor_pool_add(descpool, u, NULL))
105                 return false;
106
107         /* descriptor_pool_add accepts method descriptors, so we have to
108            check against them here before the call of
109            descriptor_to_basic_type below. */
110
111         if (u->text[0] == '(') {
112                 exceptions_throw_classformaterror(c, "Method descriptor used for field");
113                 return false;
114         }
115
116 #ifdef ENABLE_VERIFIER
117         if (opt_verify) {
118                 /* check name */
119                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
120                         exceptions_throw_classformaterror(c,
121                                                                                           "Illegal Field name \"%s\"",
122                                                                                           f->name->text);
123                         return false;
124                 }
125
126                 /* check flag consistency */
127                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
128
129                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
130                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
131                         exceptions_throw_classformaterror(c,
132                                                                                           "Illegal field modifiers: 0x%X",
133                                                                                           f->flags);
134                         return false;
135                 }
136
137                 if (c->flags & ACC_INTERFACE) {
138                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
139                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
140                                 f->flags & ACC_TRANSIENT) {
141                                 exceptions_throw_classformaterror(c,
142                                                                                                   "Illegal field modifiers: 0x%X",
143                                                                                                   f->flags);
144                                 return false;
145                         }
146                 }
147         }
148 #endif /* ENABLE_VERIFIER */
149
150         /* data type */
151
152         f->type = descriptor_to_basic_type(f->descriptor);
153
154         /* For static-fields allocate memory for the value and set the
155            value to 0. */
156
157         if (f->flags & ACC_STATIC) {
158                 switch (f->type) {
159                 case TYPE_INT:
160                 case TYPE_LNG:
161                 case TYPE_FLT:
162                 case TYPE_DBL:
163                         f->value = NEW(imm_union);
164                         break;
165
166                 case TYPE_ADR:
167 #if defined(ENABLE_GC_CACAO)
168                         f->value = NEW(imm_union);
169 #else
170                         f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
171 #endif
172                         break;
173
174                 default:
175                         vm_abort("field_load: invalid field type %d", f->type);
176                 }
177
178                 /* Set the field to zero, for float and double fields set the
179                    correct 0.0 value. */
180
181                 switch (f->type) {
182                 case TYPE_INT:
183                 case TYPE_LNG:
184                 case TYPE_ADR:
185                         f->value->l = 0;
186                         break;
187
188                 case TYPE_FLT:
189                         f->value->f = 0.0;
190                         break;
191
192                 case TYPE_DBL:
193                         f->value->d = 0.0;
194                         break;
195                 }
196         }
197         else {
198                 /* For instance-fields set the offset to 0. */
199
200                 f->offset = 0;
201
202                 /* For final fields, which are not static, we need a value
203                    structure. */
204
205                 if (f->flags & ACC_FINAL) {
206                         f->value = NEW(imm_union);
207                         /* XXX hack */
208                         f->value->l = 0;
209                 }
210
211                 switch (f->type) {
212                 case TYPE_ADR:
213                         c->flags |= ACC_CLASS_HAS_POINTERS;
214                         break;
215                 }
216         }
217
218         /* read attributes */
219
220         if (!suck_check_classbuffer_size(cb, 2))
221                 return false;
222
223         attrnum = suck_u2(cb);
224
225         for (i = 0; i < attrnum; i++) {
226                 if (!suck_check_classbuffer_size(cb, 2))
227                         return false;
228
229                 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
230                         return false;
231
232                 if (u == utf_ConstantValue) {
233                         if (!suck_check_classbuffer_size(cb, 4 + 2))
234                                 return false;
235
236                         /* check attribute length */
237
238                         if (suck_u4(cb) != 2) {
239                                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
240                                 return false;
241                         }
242                         
243                         /* constant value attribute */
244
245                         if (pindex != field_load_NOVALUE) {
246                                 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
247                                 return false;
248                         }
249                         
250                         /* index of value in constantpool */
251
252                         pindex = suck_u2(cb);
253                 
254                         /* initialize field with value from constantpool */             
255
256                         switch (f->type) {
257                         case TYPE_INT: {
258                                 constant_integer *ci; 
259
260                                 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
261                                         return false;
262
263                                 f->value->i = ci->value;
264                         }
265                         break;
266                                         
267                         case TYPE_LNG: {
268                                 constant_long *cl; 
269
270                                 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
271                                         return false;
272
273                                 f->value->l = cl->value;
274                         }
275                         break;
276
277                         case TYPE_FLT: {
278                                 constant_float *cf;
279
280                                 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
281                                         return false;
282
283                                 f->value->f = cf->value;
284                         }
285                         break;
286                                                                                         
287                         case TYPE_DBL: {
288                                 constant_double *cd;
289
290                                 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
291                                         return false;
292
293                                 f->value->d = cd->value;
294                         }
295                         break;
296                                                 
297                         case TYPE_ADR:
298                                 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
299                                         return false;
300
301                                 /* Create Java-string from compressed UTF8-string. */
302
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->class->classloader);
368         }
369         else {
370                 c = primitive_class_get_by_type(td->decltype);
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         /* empty */
386 }
387
388
389 /* field_get_annotations ******************************************************
390
391    Gets a fields' annotations (or NULL if none).
392
393 *******************************************************************************/
394
395 java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
396 {
397 #if defined(ENABLE_ANNOTATIONS)
398         classinfo               *c;
399         int                      slot;
400         annotation_bytearray_t  *ba;
401         java_handle_bytearray_t *annotations;
402
403         c           = f->class;
404         slot        = f - c->fields;
405         annotations = NULL;
406         
407         if (c->field_annotations != NULL && c->field_annotations->size > slot) {
408                 ba = c->field_annotations->data[slot];
409                 
410                 if (ba != NULL) {
411                         annotations = builtin_newarray_byte(ba->size);
412                         
413                         if (annotations != NULL) {
414                                 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
415                         }
416                 }
417         }
418         
419         return annotations;
420 #else
421         return NULL;
422 #endif
423 }
424
425
426 /* field_printflags ************************************************************
427
428    (debugging only)
429
430 *******************************************************************************/
431
432 #if !defined(NDEBUG)
433 void field_printflags(fieldinfo *f)
434 {
435         if (f == NULL) {
436                 printf("NULL");
437                 return;
438         }
439
440         if (f->flags & ACC_PUBLIC)       printf(" PUBLIC");
441         if (f->flags & ACC_PRIVATE)      printf(" PRIVATE");
442         if (f->flags & ACC_PROTECTED)    printf(" PROTECTED");
443         if (f->flags & ACC_STATIC)       printf(" STATIC");
444         if (f->flags & ACC_FINAL)        printf(" FINAL");
445         if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
446         if (f->flags & ACC_VOLATILE)     printf(" VOLATILE");
447         if (f->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
448         if (f->flags & ACC_NATIVE)       printf(" NATIVE");
449         if (f->flags & ACC_INTERFACE)    printf(" INTERFACE");
450         if (f->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
451 }
452 #endif
453
454
455 /* field_print *****************************************************************
456
457    (debugging only)
458
459 *******************************************************************************/
460
461 #if !defined(NDEBUG)
462 void field_print(fieldinfo *f)
463 {
464         if (f == NULL) {
465                 printf("(fieldinfo*)NULL");
466                 return;
467         }
468
469         utf_display_printable_ascii_classname(f->class->name);
470         printf(".");
471         utf_display_printable_ascii(f->name);
472         printf(" ");
473         utf_display_printable_ascii(f->descriptor);     
474
475         field_printflags(f);
476 }
477 #endif
478
479
480 /* field_println ***************************************************************
481
482    (debugging only)
483
484 *******************************************************************************/
485
486 #if !defined(NDEBUG)
487 void field_println(fieldinfo *f)
488 {
489         field_print(f);
490         printf("\n");
491 }
492 #endif
493
494 /* field_fieldref_print ********************************************************
495
496    (debugging only)
497
498 *******************************************************************************/
499
500 #if !defined(NDEBUG)
501 void field_fieldref_print(constant_FMIref *fr)
502 {
503         if (fr == NULL) {
504                 printf("(constant_FMIref *)NULL");
505                 return;
506         }
507
508         if (IS_FMIREF_RESOLVED(fr)) {
509                 printf("<field> ");
510                 field_print(fr->p.field);
511         }
512         else {
513                 printf("<fieldref> ");
514                 utf_display_printable_ascii_classname(fr->p.classref->name);
515                 printf(".");
516                 utf_display_printable_ascii(fr->name);
517                 printf(" ");
518                 utf_display_printable_ascii(fr->descriptor);
519         }
520 }
521 #endif
522
523 /* field_fieldref_println ******************************************************
524
525    (debugging only)
526
527 *******************************************************************************/
528
529 #if !defined(NDEBUG)
530 void field_fieldref_println(constant_FMIref *fr)
531 {
532         field_fieldref_print(fr);
533         printf("\n");
534 }
535 #endif
536
537 /*
538  * These are local overrides for various environment variables in Emacs.
539  * Please do not remove this and leave it at the end of the file, where
540  * Emacs will automagically detect them.
541  * ---------------------------------------------------------------------
542  * Local variables:
543  * mode: c
544  * indent-tabs-mode: t
545  * c-basic-offset: 4
546  * tab-width: 4
547  * End:
548  */