1 /* src/vmcore/field.c - field functions
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
8 This file is part of CACAO.
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.
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.
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
25 $Id: field.c 8315 2007-08-15 22:49:20Z panzi $
36 #include "mm/memory.h"
40 #include "mm/memory.h"
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"
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"
60 /* field_load ******************************************************************
62 Load everything about a class field from the class file and fill a
65 *******************************************************************************/
67 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
69 bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
73 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
82 /* Get access flags. */
84 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
87 f->flags = suck_u2(cb);
91 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
98 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
102 f->parseddesc = NULL;
104 if (!descriptor_pool_add(descpool, u, NULL))
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. */
111 if (u->text[0] == '(') {
112 exceptions_throw_classformaterror(c, "Method descriptor used for field");
116 #ifdef ENABLE_VERIFIER
119 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
120 exceptions_throw_classformaterror(c,
121 "Illegal Field name \"%s\"",
126 /* check flag consistency */
127 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
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",
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",
148 #endif /* ENABLE_VERIFIER */
152 f->type = descriptor_to_basic_type(f->descriptor);
154 /* For static-fields allocate memory for the value and set the
157 if (f->flags & ACC_STATIC) {
163 f->value = NEW(imm_union);
167 #if defined(ENABLE_GC_CACAO)
168 f->value = NEW(imm_union);
170 f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
175 vm_abort("field_load: invalid field type %d", f->type);
178 /* Set the field to zero, for float and double fields set the
179 correct 0.0 value. */
198 /* For instance-fields set the offset to 0. */
202 /* For final fields, which are not static, we need a value
205 if (f->flags & ACC_FINAL) {
206 f->value = NEW(imm_union);
213 c->flags |= ACC_CLASS_HAS_POINTERS;
218 /* read attributes */
220 if (!suck_check_classbuffer_size(cb, 2))
223 attrnum = suck_u2(cb);
225 for (i = 0; i < attrnum; i++) {
226 if (!suck_check_classbuffer_size(cb, 2))
229 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
232 if (u == utf_ConstantValue) {
233 if (!suck_check_classbuffer_size(cb, 4 + 2))
236 /* check attribute length */
238 if (suck_u4(cb) != 2) {
239 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
243 /* constant value attribute */
245 if (pindex != field_load_NOVALUE) {
246 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
250 /* index of value in constantpool */
252 pindex = suck_u2(cb);
254 /* initialize field with value from constantpool */
258 constant_integer *ci;
260 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
263 f->value->i = ci->value;
270 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
273 f->value->l = cl->value;
280 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
283 f->value->f = cf->value;
290 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
293 f->value->d = cd->value;
298 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
301 /* Create Java-string from compressed UTF8-string. */
303 f->value->a = literalstring_new(u);
307 vm_abort("field_load: invalid field type %d", f->type);
310 #if defined(ENABLE_JAVASE)
311 else if (u == utf_Signature) {
314 if (!loader_load_attribute_signature(cb, &(f->signature)))
318 #if defined(ENABLE_ANNOTATIONS)
319 else if (u == utf_RuntimeVisibleAnnotations) {
320 /* RuntimeVisibleAnnotations */
321 if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
324 else if (u == utf_RuntimeInvisibleAnnotations) {
325 /* RuntimeInvisibleAnnotations */
326 if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
332 /* unknown attribute */
334 if (!loader_skip_attribute_body(cb))
339 /* everything was ok */
345 /* field_get_type **************************************************************
347 Returns the type of the field as class.
349 *******************************************************************************/
351 classinfo *field_get_type(fieldinfo *f)
359 if (td->type == TYPE_ADR) {
360 assert(td->classref);
362 u = td->classref->name;
364 /* load the class of the field-type with the field's
367 c = load_class_from_classloader(u, f->class->classloader);
370 c = primitive_class_get_by_type(td->decltype);
377 /* field_free ******************************************************************
379 Frees a fields' resources.
381 *******************************************************************************/
383 void field_free(fieldinfo *f)
389 #if defined(ENABLE_ANNOTATIONS)
390 /* field_get_annotations ******************************************************
392 Gets a fields' annotations (or NULL if none).
394 *******************************************************************************/
396 java_bytearray *field_get_annotations(fieldinfo *f)
398 classinfo *c = f->class;
399 int slot = f - c->fields;
400 annotation_bytearray_t *ba = NULL;
401 java_bytearray *annotations = NULL;
403 if (c->field_annotations != NULL && c->field_annotations->size > slot) {
404 ba = c->field_annotations->data[slot];
407 annotations = builtin_newarray_byte(ba->size);
409 if (annotations != NULL) {
410 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
420 /* field_printflags ************************************************************
424 *******************************************************************************/
427 void field_printflags(fieldinfo *f)
434 if (f->flags & ACC_PUBLIC) printf(" PUBLIC");
435 if (f->flags & ACC_PRIVATE) printf(" PRIVATE");
436 if (f->flags & ACC_PROTECTED) printf(" PROTECTED");
437 if (f->flags & ACC_STATIC) printf(" STATIC");
438 if (f->flags & ACC_FINAL) printf(" FINAL");
439 if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
440 if (f->flags & ACC_VOLATILE) printf(" VOLATILE");
441 if (f->flags & ACC_TRANSIENT) printf(" TRANSIENT");
442 if (f->flags & ACC_NATIVE) printf(" NATIVE");
443 if (f->flags & ACC_INTERFACE) printf(" INTERFACE");
444 if (f->flags & ACC_ABSTRACT) printf(" ABSTRACT");
449 /* field_print *****************************************************************
453 *******************************************************************************/
456 void field_print(fieldinfo *f)
459 printf("(fieldinfo*)NULL");
463 utf_display_printable_ascii_classname(f->class->name);
465 utf_display_printable_ascii(f->name);
467 utf_display_printable_ascii(f->descriptor);
474 /* field_println ***************************************************************
478 *******************************************************************************/
481 void field_println(fieldinfo *f)
488 /* field_fieldref_print ********************************************************
492 *******************************************************************************/
495 void field_fieldref_print(constant_FMIref *fr)
498 printf("(constant_FMIref *)NULL");
502 if (IS_FMIREF_RESOLVED(fr)) {
504 field_print(fr->p.field);
507 printf("<fieldref> ");
508 utf_display_printable_ascii_classname(fr->p.classref->name);
510 utf_display_printable_ascii(fr->name);
512 utf_display_printable_ascii(fr->descriptor);
517 /* field_fieldref_println ******************************************************
521 *******************************************************************************/
524 void field_fieldref_println(constant_FMIref *fr)
526 field_fieldref_print(fr);
532 * These are local overrides for various environment variables in Emacs.
533 * Please do not remove this and leave it at the end of the file, where
534 * Emacs will automagically detect them.
535 * ---------------------------------------------------------------------
538 * indent-tabs-mode: t