1 /* src/vm/annotation.c - class annotations
3 Copyright (C) 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
31 #include "native/llni.h"
33 #include "mm/memory.h"
35 #include "toolbox/logging.h"
37 #include "vm/annotation.h"
39 #include "vm/jit/builtin.hpp"
41 #include "vm/loader.hpp"
42 #include "vm/primitive.hpp"
43 #include "vm/suck.hpp"
46 #if !defined(ENABLE_ANNOTATIONS)
47 # error annotation support has to be enabled when compling this file!
51 /* annotation_bytearrays_resize ***********************************************
53 Resize an array of bytearrays.
56 bytearrays.....array of bytearrays
57 size...........new size of the refered array
60 The new array if a resize was neccessarry, the old if the given size
61 equals the current size or NULL if an error occured.
63 *******************************************************************************/
65 static java_handle_objectarray_t *annotation_bytearrays_resize(
66 java_handle_objectarray_t *bytearrays, uint32_t size)
68 java_handle_objectarray_t *newbas = NULL; /* new array */
69 uint32_t minsize = 0; /* count of object refs to copy */
70 uint32_t oldsize = 0; /* size of old array */
72 if (bytearrays != NULL) {
73 oldsize = array_length_get((java_handle_t*)bytearrays);
75 /* if the size already fits do nothing */
76 if (size == oldsize) {
81 newbas = builtin_anewarray(size,
82 Primitive_get_arrayclass_by_type(PRIMITIVETYPE_BYTE));
84 /* is there a old byte array array? */
85 if (newbas != NULL && bytearrays != NULL) {
86 minsize = size < oldsize ? size : oldsize;
90 LLNI_array_data(newbas), LLNI_array_data(bytearrays),
91 java_object_t*, minsize);
99 /* annotation_bytearrays_insert ***********************************************
101 Insert a bytearray into an array of bytearrays.
104 bytearrays........array of bytearrays where 'bytearray' has to be
105 inserted at position 'index'.
106 index.............position where 'ba' has to be inserted into
108 bytearray.........byte array which has to be inserted into
112 The new array if a resize was neccessarry, the old if the given size
113 equals the current size or NULL if an error occured.
115 *******************************************************************************/
117 static java_handle_t *annotation_bytearrays_insert(
118 java_handle_t *bytearrays, uint32_t index,
119 java_handle_bytearray_t *bytearray)
121 java_handle_objectarray_t *bas; /* bytearrays */
122 uint32_t size = 0; /* current size of the array */
124 /* do nothing if NULL is inserted but no array exists */
125 if (bytearray == NULL && bytearrays == NULL) {
129 /* get lengths if array exists */
130 if (bytearrays != NULL) {
131 size = array_length_get(bytearrays);
134 bas = (java_handle_objectarray_t*)bytearrays;
136 if (bytearray == NULL) {
137 /* insert NULL only if array is big enough */
139 array_objectarray_element_set(bas, index, NULL);
143 /* resize array if it's not enough for inserted value */
145 bas = annotation_bytearrays_resize(bas, index + 1);
153 array_objectarray_element_set(bas, index, (java_handle_t*)bytearray);
156 return (java_handle_t*)bas;
160 /* annotation_load_attribute_body *********************************************
162 This function loads the body of a generic attribute.
164 XXX: Maybe this function should be called loader_load_attribute_body and
165 located in vm/loader.c?
168 u2 attribute_name_index;
170 u1 info[attribute_length];
174 cb.................classbuffer from which to read the data.
175 errormsg_prefix....prefix for error messages (if any).
178 attribute..........bytearray-pointer which will be set to the read data.
181 true if all went good. false otherwhise.
183 *******************************************************************************/
185 static bool annotation_load_attribute_body(classbuffer *cb,
186 java_handle_bytearray_t **attribute, const char *errormsg_prefix)
188 uint32_t size = 0; /* size of the attribute */
189 java_handle_bytearray_t *ba = NULL; /* the raw attributes' bytes */
192 assert(attribute != NULL);
194 if (!suck_check_classbuffer_size(cb, 4)) {
195 log_println("%s: size missing", errormsg_prefix);
199 /* load attribute_length */
202 if (!suck_check_classbuffer_size(cb, size)) {
203 log_println("%s: invalid size", errormsg_prefix);
207 /* if attribute_length == 0 then NULL is
208 * the right value for this attribute */
210 ba = builtin_newarray_byte(size);
220 suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size);
232 /* annotation_load_method_attribute_annotationdefault *************************
234 Load annotation default value.
236 AnnotationDefault_attribute {
237 u2 attribute_name_index;
239 element_value default_value;
243 cb.................classbuffer from which to read the data.
244 m..................methodinfo for the method of which the annotation
245 default value is read and into which the value is
249 true if all went good. false otherwhise.
251 *******************************************************************************/
253 bool annotation_load_method_attribute_annotationdefault(
254 classbuffer *cb, methodinfo *m)
257 /* the slot of the method */
258 java_handle_bytearray_t *annotationdefault = NULL;
259 /* unparsed annotation defalut value */
260 java_handle_t *annotationdefaults = NULL;
261 /* array of unparsed annotation default values */
266 LLNI_classinfo_field_get(
267 m->clazz, method_annotationdefaults, annotationdefaults);
269 if (!annotation_load_attribute_body(
270 cb, &annotationdefault,
271 "invalid annotation default method attribute")) {
275 if (annotationdefault != NULL) {
276 slot = m - m->clazz->methods;
277 annotationdefaults = annotation_bytearrays_insert(
278 annotationdefaults, slot, annotationdefault);
280 if (annotationdefaults == NULL) {
284 LLNI_classinfo_field_set(
285 m->clazz, method_annotationdefaults, annotationdefaults);
292 /* annotation_load_method_attribute_runtimevisibleparameterannotations ********
294 Load runtime visible parameter annotations.
296 RuntimeVisibleParameterAnnotations_attribute {
297 u2 attribute_name_index;
302 annotation annotations[num_annotations];
303 } parameter_annotations[num_parameters];
307 cb.................classbuffer from which to read the data.
308 m..................methodinfo for the method of which the parameter
309 annotations are read and into which the parameter
310 annotations are stored into.
313 true if all went good. false otherwhise.
315 *******************************************************************************/
317 bool annotation_load_method_attribute_runtimevisibleparameterannotations(
318 classbuffer *cb, methodinfo *m)
321 /* the slot of the method */
322 java_handle_bytearray_t *annotations = NULL;
323 /* unparsed parameter annotations */
324 java_handle_t *parameterannotations = NULL;
325 /* array of unparsed parameter annotations */
330 LLNI_classinfo_field_get(
331 m->clazz, method_parameterannotations, parameterannotations);
333 if (!annotation_load_attribute_body(
335 "invalid runtime visible parameter annotations method attribute")) {
339 if (annotations != NULL) {
340 slot = m - m->clazz->methods;
341 parameterannotations = annotation_bytearrays_insert(
342 parameterannotations, slot, annotations);
344 if (parameterannotations == NULL) {
348 LLNI_classinfo_field_set(
349 m->clazz, method_parameterannotations, parameterannotations);
356 /* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
358 Load runtime invisible parameter annotations.
360 <quote cite="http://jcp.org/en/jsr/detail?id=202">
361 The RuntimeInvisibleParameterAnnotations attribute is similar to the
362 RuntimeVisibleParameterAnnotations attribute, except that the annotations
363 represented by a RuntimeInvisibleParameterAnnotations attribute must not be
364 made available for return by reflective APIs, unless the the JVM has
365 specifically been instructed to retain these annotations via some
366 implementation-specific mechanism such as a command line flag. In the
367 absence of such instructions, the JVM ignores this attribute.
370 Hotspot loads them into the same bytearray as the runtime visible parameter
371 annotations (after the runtime visible parameter annotations). But in J2SE
372 the bytearray will only be parsed as if there is only one annotation
373 structure in it, so the runtime invisible parameter annotatios will be
376 Therefore I do not even bother to read them.
378 RuntimeInvisibleParameterAnnotations_attribute {
379 u2 attribute_name_index;
384 annotation annotations[num_annotations];
385 } parameter_annotations[num_parameters];
389 cb.................classbuffer from which to read the data.
390 m..................methodinfo for the method of which the parameter
391 annotations are read and into which the parameter
392 annotations are stored into.
395 true if all went good. false otherwhise.
397 *******************************************************************************/
399 bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
400 classbuffer *cb, methodinfo *m)
402 return loader_skip_attribute_body(cb);
406 /* annotation_load_class_attribute_runtimevisibleannotations ******************
408 Load runtime visible annotations of a class.
411 cb........the classbuffer from which the attribute has to be loaded.
414 true if all went good. false otherwhise.
416 *******************************************************************************/
418 bool annotation_load_class_attribute_runtimevisibleannotations(
421 java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
423 if (!annotation_load_attribute_body(
425 "invalid runtime visible annotations class attribute")) {
429 LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations);
435 /* annotation_load_class_attribute_runtimeinvisibleannotations ****************
437 Load runtime invisible annotations of a class (just skip them).
440 cb........the classbuffer from which the attribute has to be loaded.
443 true if all went good. false otherwhise.
445 *******************************************************************************/
447 bool annotation_load_class_attribute_runtimeinvisibleannotations(
450 return loader_skip_attribute_body(cb);
454 /* annotation_load_method_attribute_runtimevisibleannotations *****************
456 Load runtime visible annotations of a method.
459 cb........the classbuffer from which the attribute has to be loaded.
460 m.........the method of which the runtime visible annotations have
464 true if all went good. false otherwhise.
466 *******************************************************************************/
468 bool annotation_load_method_attribute_runtimevisibleannotations(
469 classbuffer *cb, methodinfo *m)
472 /* slot of the method */
473 java_handle_bytearray_t *annotations = NULL;
474 /* unparsed annotations */
475 java_handle_t *method_annotations = NULL;
476 /* array of unparsed method annotations */
481 LLNI_classinfo_field_get(
482 m->clazz, method_annotations, method_annotations);
484 if (!annotation_load_attribute_body(
486 "invalid runtime visible annotations method attribute")) {
490 if (annotations != NULL) {
491 slot = m - m->clazz->methods;
492 method_annotations = annotation_bytearrays_insert(
493 method_annotations, slot, annotations);
495 if (method_annotations == NULL) {
499 LLNI_classinfo_field_set(
500 m->clazz, method_annotations, method_annotations);
507 /* annotation_load_method_attribute_runtimeinvisibleannotations ****************
509 Load runtime invisible annotations of a method (just skip them).
512 cb........the classbuffer from which the attribute has to be loaded.
513 m.........the method of which the runtime invisible annotations have
517 true if all went good. false otherwhise.
519 *******************************************************************************/
521 bool annotation_load_method_attribute_runtimeinvisibleannotations(
522 classbuffer *cb, methodinfo *m)
524 return loader_skip_attribute_body(cb);
528 /* annotation_load_field_attribute_runtimevisibleannotations ******************
530 Load runtime visible annotations of a field.
533 cb........the classbuffer from which the attribute has to be loaded.
534 f.........the field of which the runtime visible annotations have
538 true if all went good. false otherwhise.
540 *******************************************************************************/
542 bool annotation_load_field_attribute_runtimevisibleannotations(
543 classbuffer *cb, fieldinfo *f)
546 /* slot of the field */
547 java_handle_bytearray_t *annotations = NULL;
548 /* unparsed annotations */
549 java_handle_t *field_annotations = NULL;
550 /* array of unparsed field annotations */
555 LLNI_classinfo_field_get(
556 f->clazz, field_annotations, field_annotations);
558 if (!annotation_load_attribute_body(
560 "invalid runtime visible annotations field attribute")) {
564 if (annotations != NULL) {
565 slot = f - f->clazz->fields;
566 field_annotations = annotation_bytearrays_insert(
567 field_annotations, slot, annotations);
569 if (field_annotations == NULL) {
573 LLNI_classinfo_field_set(
574 f->clazz, field_annotations, field_annotations);
581 /* annotation_load_field_attribute_runtimeinvisibleannotations ****************
583 Load runtime invisible annotations of a field (just skip them).
586 cb........the classbuffer from which the attribute has to be loaded.
587 f.........the field of which the runtime invisible annotations have
591 true if all went good. false otherwhise.
593 *******************************************************************************/
595 bool annotation_load_field_attribute_runtimeinvisibleannotations(
596 classbuffer *cb, fieldinfo *f)
598 return loader_skip_attribute_body(cb);
603 * These are local overrides for various environment variables in Emacs.
604 * Please do not remove this and leave it at the end of the file, where
605 * Emacs will automagically detect them.
606 * ---------------------------------------------------------------------
609 * indent-tabs-mode: t
613 * vim:noexpandtab:sw=4:ts=4: