1 /* src/vm/field.cpp - field functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
32 #include "mm/memory.h"
34 #include "native/llni.h"
38 #include "vm/annotation.h"
39 #include "vm/array.hpp"
40 #include "vm/jit/builtin.hpp"
41 #include "vm/class.hpp"
42 #include "vm/descriptor.h"
43 #include "vm/exceptions.hpp"
44 #include "vm/field.hpp"
45 #include "vm/global.h"
46 #include "vm/loader.hpp"
47 #include "vm/options.h"
48 #include "vm/primitive.hpp"
49 #include "vm/references.h"
50 #include "vm/string.hpp"
51 #include "vm/suck.hpp"
56 /* field_load ******************************************************************
58 Load everything about a class field from the class file and fill a
61 *******************************************************************************/
63 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
65 bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
69 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
78 /* Get access flags. */
80 if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
83 f->flags = suck_u2(cb);
87 if (!(u = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
94 if (!(u = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
100 if (!descriptor_pool_add(descpool, u, NULL))
103 /* descriptor_pool_add accepts method descriptors, so we have to
104 check against them here before the call of
105 descriptor_to_basic_type below. */
107 if (u->text[0] == '(') {
108 exceptions_throw_classformaterror(c, "Method descriptor used for field");
112 #ifdef ENABLE_VERIFIER
115 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
116 exceptions_throw_classformaterror(c,
117 "Illegal Field name \"%s\"",
122 /* check flag consistency */
123 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
125 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
126 ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
127 exceptions_throw_classformaterror(c,
128 "Illegal field modifiers: 0x%X",
133 if (c->flags & ACC_INTERFACE) {
134 if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
135 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
136 f->flags & ACC_TRANSIENT) {
137 exceptions_throw_classformaterror(c,
138 "Illegal field modifiers: 0x%X",
144 #endif /* ENABLE_VERIFIER */
148 f->type = descriptor_to_basic_type(f->descriptor);
150 /* For static-fields allocate memory for the value and set the
153 if (f->flags & ACC_STATIC) {
159 f->value = NEW(imm_union);
163 #if !defined(ENABLE_GC_BOEHM)
164 f->value = NEW(imm_union);
166 f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
171 vm_abort("field_load: invalid field type %d", f->type);
174 /* Set the field to zero, for float and double fields set the
175 correct 0.0 value. */
194 /* For instance-fields set the offset to 0. */
198 /* For final fields, which are not static, we need a value
201 if (f->flags & ACC_FINAL) {
202 f->value = NEW(imm_union);
209 c->flags |= ACC_CLASS_HAS_POINTERS;
214 /* read attributes */
216 if (!suck_check_classbuffer_size(cb, 2))
219 attrnum = suck_u2(cb);
221 for (i = 0; i < attrnum; i++) {
222 if (!suck_check_classbuffer_size(cb, 2))
225 if (!(u = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
228 if (u == utf_ConstantValue) {
229 if (!suck_check_classbuffer_size(cb, 4 + 2))
232 /* check attribute length */
234 if (suck_u4(cb) != 2) {
235 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
239 /* constant value attribute */
241 if (pindex != field_load_NOVALUE) {
242 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
246 /* index of value in constantpool */
248 pindex = suck_u2(cb);
250 /* initialize field with value from constantpool */
254 constant_integer *ci;
256 if (!(ci = (constant_integer*) class_getconstant(c, pindex, CONSTANT_Integer)))
259 f->value->i = ci->value;
266 if (!(cl = (constant_long*) class_getconstant(c, pindex, CONSTANT_Long)))
269 f->value->l = cl->value;
276 if (!(cf = (constant_float*) class_getconstant(c, pindex, CONSTANT_Float)))
279 f->value->f = cf->value;
286 if (!(cd = (constant_double*) class_getconstant(c, pindex, CONSTANT_Double)))
289 f->value->d = cd->value;
294 if (!(u = (utf*) class_getconstant(c, pindex, CONSTANT_String)))
297 /* Create Java-string from compressed UTF8-string. */
299 f->value->a = literalstring_new(u);
303 vm_abort("field_load: invalid field type %d", f->type);
306 #if defined(ENABLE_JAVASE)
307 else if (u == utf_Signature) {
310 if (!loader_load_attribute_signature(cb, &(f->signature)))
314 #if defined(ENABLE_ANNOTATIONS)
315 else if (u == utf_RuntimeVisibleAnnotations) {
316 /* RuntimeVisibleAnnotations */
317 if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
320 else if (u == utf_RuntimeInvisibleAnnotations) {
321 /* RuntimeInvisibleAnnotations */
322 if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
328 /* unknown attribute */
330 if (!loader_skip_attribute_body(cb))
335 /* everything was ok */
341 /* field_get_type **************************************************************
343 Returns the type of the field as class.
345 *******************************************************************************/
347 classinfo *field_get_type(fieldinfo *f)
355 if (td->type == TYPE_ADR) {
356 assert(td->classref);
358 u = td->classref->name;
360 /* load the class of the field-type with the field's
363 c = load_class_from_classloader(u, f->clazz->classloader);
366 c = Primitive::get_class_by_type(td->primitivetype);
373 /* field_free ******************************************************************
375 Frees a fields' resources.
377 *******************************************************************************/
379 void field_free(fieldinfo *f)
381 /* free memory for fields which have a value */
384 #if defined(ENABLE_GC_BOEHM)
385 if (f->type != TYPE_ADR)
387 FREE(f->value, imm_union);
391 /* field_get_annotations ******************************************************
393 Get a fields' unparsed annotations in a byte array.
396 f........the field of which the annotations should be returned
399 The unparsed annotations in a byte array (or NULL if there aren't any).
401 *******************************************************************************/
403 java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
405 #if defined(ENABLE_ANNOTATIONS)
406 classinfo *c; /* declaring class */
407 int slot; /* slot of this field */
408 java_handle_bytearray_t *annotations; /* unparsed annotations */
409 java_handle_t *field_annotations; /* array of unparsed */
410 /* annotations of all fields of the declaring class */
413 slot = f - c->fields;
416 LLNI_classinfo_field_get(c, field_annotations, field_annotations);
418 /* the field_annotations array might be shorter then the field
419 * count if the fields above a certain index have no annotations.
421 if (field_annotations != NULL &&
422 array_length_get(field_annotations) > slot) {
423 annotations = (java_handle_bytearray_t*)array_objectarray_element_get(
424 (java_handle_objectarray_t*)field_annotations, slot);
434 /* field_printflags ************************************************************
438 *******************************************************************************/
441 void field_printflags(fieldinfo *f)
448 if (f->flags & ACC_PUBLIC) printf(" PUBLIC");
449 if (f->flags & ACC_PRIVATE) printf(" PRIVATE");
450 if (f->flags & ACC_PROTECTED) printf(" PROTECTED");
451 if (f->flags & ACC_STATIC) printf(" STATIC");
452 if (f->flags & ACC_FINAL) printf(" FINAL");
453 if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
454 if (f->flags & ACC_VOLATILE) printf(" VOLATILE");
455 if (f->flags & ACC_TRANSIENT) printf(" TRANSIENT");
456 if (f->flags & ACC_NATIVE) printf(" NATIVE");
457 if (f->flags & ACC_INTERFACE) printf(" INTERFACE");
458 if (f->flags & ACC_ABSTRACT) printf(" ABSTRACT");
463 /* field_print *****************************************************************
467 *******************************************************************************/
470 void field_print(fieldinfo *f)
473 printf("(fieldinfo*)NULL");
477 utf_display_printable_ascii_classname(f->clazz->name);
479 utf_display_printable_ascii(f->name);
481 utf_display_printable_ascii(f->descriptor);
485 if (!(f->flags & ACC_STATIC)) {
486 printf(", offset: %d", f->offset);
492 /* field_println ***************************************************************
496 *******************************************************************************/
499 void field_println(fieldinfo *f)
506 /* field_fieldref_print ********************************************************
510 *******************************************************************************/
513 void field_fieldref_print(constant_FMIref *fr)
516 printf("(constant_FMIref *)NULL");
520 if (IS_FMIREF_RESOLVED(fr)) {
522 field_print(fr->p.field);
525 printf("<fieldref> ");
526 utf_display_printable_ascii_classname(fr->p.classref->name);
528 utf_display_printable_ascii(fr->name);
530 utf_display_printable_ascii(fr->descriptor);
535 /* field_fieldref_println ******************************************************
539 *******************************************************************************/
542 void field_fieldref_println(constant_FMIref *fr)
544 field_fieldref_print(fr);
550 * These are local overrides for various environment variables in Emacs.
551 * Please do not remove this and leave it at the end of the file, where
552 * Emacs will automagically detect them.
553 * ---------------------------------------------------------------------
556 * indent-tabs-mode: t
560 * vim:noexpandtab:sw=4:ts=4: