1 /* src/vm/annotation.cpp - 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.hpp"
35 #include "toolbox/logging.hpp"
37 #include "vm/annotation.hpp"
38 #include "vm/array.hpp"
39 #include "vm/jit/builtin.hpp"
40 #include "vm/class.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 uint32_t minsize = 0; /* count of object refs to copy */
69 uint32_t oldsize = 0; /* size of old array */
71 ObjectArray bas(bytearrays);
73 if (bytearrays != NULL) {
74 oldsize = bas.get_length();
76 /* if the size already fits do nothing */
77 if (size == oldsize) {
82 // Allocate new array on the heap.
84 ObjectArray newbas(size,
85 Primitive::get_arrayclass_by_type(PRIMITIVETYPE_BYTE));
87 /* is there a old byte array array? */
88 if (newbas.is_non_null() && bytearrays != NULL) {
89 minsize = size < oldsize ? size : oldsize;
93 newbas.get_raw_data_ptr(), bas.get_raw_data_ptr(),
94 java_object_t*, minsize);
98 return newbas.get_handle();
102 /* annotation_bytearrays_insert ***********************************************
104 Insert a bytearray into an array of bytearrays.
107 bytearrays........array of bytearrays where 'bytearray' has to be
108 inserted at position 'index'.
109 index.............position where 'ba' has to be inserted into
111 bytearray.........byte array which has to be inserted into
115 The new array if a resize was neccessarry, the old if the given size
116 equals the current size or NULL if an error occured.
118 *******************************************************************************/
120 static java_handle_t *annotation_bytearrays_insert(
121 java_handle_t *bytearrays, uint32_t index,
122 java_handle_bytearray_t *bytearray)
124 uint32_t size = 0; /* current size of the array */
126 /* do nothing if NULL is inserted but no array exists */
127 if (bytearray == NULL && bytearrays == NULL) {
131 ObjectArray bas(bytearrays);
133 /* get lengths if array exists */
134 if (bytearrays != NULL) {
135 size = bas.get_length();
138 if (bytearray == NULL) {
139 /* insert NULL only if array is big enough */
141 bas.set_element(index, NULL);
145 // XXX: We should use a clone function here!!!
146 /* resize array if it's not enough for inserted value */
148 bas = annotation_bytearrays_resize(bas.get_handle(), index + 1);
156 bas.set_element(index, (java_handle_t*) bytearray);
159 return bas.get_handle();
163 /* annotation_load_attribute_body *********************************************
165 This function loads the body of a generic attribute.
167 XXX: Maybe this function should be called loader_load_attribute_body and
168 located in vm/loader.c?
171 u2 attribute_name_index;
173 u1 info[attribute_length];
177 cb.................classbuffer from which to read the data.
178 errormsg_prefix....prefix for error messages (if any).
181 attribute..........bytearray-pointer which will be set to the read data.
184 true if all went good. false otherwhise.
186 *******************************************************************************/
188 static bool annotation_load_attribute_body(classbuffer *cb,
189 java_handle_bytearray_t **attribute, const char *errormsg_prefix)
191 uint32_t size = 0; /* size of the attribute */
194 assert(attribute != NULL);
196 if (!suck_check_classbuffer_size(cb, 4)) {
197 log_println("%s: size missing", errormsg_prefix);
201 /* load attribute_length */
204 if (!suck_check_classbuffer_size(cb, size)) {
205 log_println("%s: invalid size", errormsg_prefix);
209 /* if attribute_length == 0 then NULL is
210 * the right value for this attribute */
222 uint8_t* ptr = (uint8_t*) ba.get_raw_data_ptr();
223 suck_nbytes(ptr, cb, size);
228 *attribute = ba.get_handle();
235 /* annotation_load_method_attribute_annotationdefault *************************
237 Load annotation default value.
239 AnnotationDefault_attribute {
240 u2 attribute_name_index;
242 element_value default_value;
246 cb.................classbuffer from which to read the data.
247 m..................methodinfo for the method of which the annotation
248 default value is read and into which the value is
252 true if all went good. false otherwhise.
254 *******************************************************************************/
256 bool annotation_load_method_attribute_annotationdefault(
257 classbuffer *cb, methodinfo *m)
260 /* the slot of the method */
261 java_handle_bytearray_t *annotationdefault = NULL;
262 /* unparsed annotation defalut value */
263 java_handle_t *annotationdefaults = NULL;
264 /* array of unparsed annotation default values */
269 LLNI_classinfo_field_get(
270 m->clazz, method_annotationdefaults, annotationdefaults);
272 if (!annotation_load_attribute_body(
273 cb, &annotationdefault,
274 "invalid annotation default method attribute")) {
278 if (annotationdefault != NULL) {
279 slot = m - m->clazz->methods;
280 annotationdefaults = annotation_bytearrays_insert(
281 annotationdefaults, slot, annotationdefault);
283 if (annotationdefaults == NULL) {
287 LLNI_classinfo_field_set(
288 m->clazz, method_annotationdefaults, annotationdefaults);
295 /* annotation_load_method_attribute_runtimevisibleparameterannotations ********
297 Load runtime visible parameter annotations.
299 RuntimeVisibleParameterAnnotations_attribute {
300 u2 attribute_name_index;
305 annotation annotations[num_annotations];
306 } parameter_annotations[num_parameters];
310 cb.................classbuffer from which to read the data.
311 m..................methodinfo for the method of which the parameter
312 annotations are read and into which the parameter
313 annotations are stored into.
316 true if all went good. false otherwhise.
318 *******************************************************************************/
320 bool annotation_load_method_attribute_runtimevisibleparameterannotations(
321 classbuffer *cb, methodinfo *m)
324 /* the slot of the method */
325 java_handle_bytearray_t *annotations = NULL;
326 /* unparsed parameter annotations */
327 java_handle_t *parameterannotations = NULL;
328 /* array of unparsed parameter annotations */
333 LLNI_classinfo_field_get(
334 m->clazz, method_parameterannotations, parameterannotations);
336 if (!annotation_load_attribute_body(
338 "invalid runtime visible parameter annotations method attribute")) {
342 if (annotations != NULL) {
343 slot = m - m->clazz->methods;
344 parameterannotations = annotation_bytearrays_insert(
345 parameterannotations, slot, annotations);
347 if (parameterannotations == NULL) {
351 LLNI_classinfo_field_set(
352 m->clazz, method_parameterannotations, parameterannotations);
359 /* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
361 Load runtime invisible parameter annotations.
363 <quote cite="http://jcp.org/en/jsr/detail?id=202">
364 The RuntimeInvisibleParameterAnnotations attribute is similar to the
365 RuntimeVisibleParameterAnnotations attribute, except that the annotations
366 represented by a RuntimeInvisibleParameterAnnotations attribute must not be
367 made available for return by reflective APIs, unless the the JVM has
368 specifically been instructed to retain these annotations via some
369 implementation-specific mechanism such as a command line flag. In the
370 absence of such instructions, the JVM ignores this attribute.
373 Hotspot loads them into the same bytearray as the runtime visible parameter
374 annotations (after the runtime visible parameter annotations). But in J2SE
375 the bytearray will only be parsed as if there is only one annotation
376 structure in it, so the runtime invisible parameter annotatios will be
379 Therefore I do not even bother to read them.
381 RuntimeInvisibleParameterAnnotations_attribute {
382 u2 attribute_name_index;
387 annotation annotations[num_annotations];
388 } parameter_annotations[num_parameters];
392 cb.................classbuffer from which to read the data.
393 m..................methodinfo for the method of which the parameter
394 annotations are read and into which the parameter
395 annotations are stored into.
398 true if all went good. false otherwhise.
400 *******************************************************************************/
402 bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
403 classbuffer *cb, methodinfo *m)
405 return loader_skip_attribute_body(cb);
409 /* annotation_load_class_attribute_runtimevisibleannotations ******************
411 Load runtime visible annotations of a class.
414 cb........the classbuffer from which the attribute has to be loaded.
417 true if all went good. false otherwhise.
419 *******************************************************************************/
421 bool annotation_load_class_attribute_runtimevisibleannotations(
424 java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
426 if (!annotation_load_attribute_body(
428 "invalid runtime visible annotations class attribute")) {
432 LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations);
438 /* annotation_load_class_attribute_runtimeinvisibleannotations ****************
440 Load runtime invisible annotations of a class (just skip them).
443 cb........the classbuffer from which the attribute has to be loaded.
446 true if all went good. false otherwhise.
448 *******************************************************************************/
450 bool annotation_load_class_attribute_runtimeinvisibleannotations(
453 return loader_skip_attribute_body(cb);
457 /* annotation_load_method_attribute_runtimevisibleannotations *****************
459 Load runtime visible annotations of a method.
462 cb........the classbuffer from which the attribute has to be loaded.
463 m.........the method of which the runtime visible annotations have
467 true if all went good. false otherwhise.
469 *******************************************************************************/
471 bool annotation_load_method_attribute_runtimevisibleannotations(
472 classbuffer *cb, methodinfo *m)
475 /* slot of the method */
476 java_handle_bytearray_t *annotations = NULL;
477 /* unparsed annotations */
478 java_handle_t *method_annotations = NULL;
479 /* array of unparsed method annotations */
484 LLNI_classinfo_field_get(
485 m->clazz, method_annotations, method_annotations);
487 if (!annotation_load_attribute_body(
489 "invalid runtime visible annotations method attribute")) {
493 if (annotations != NULL) {
494 slot = m - m->clazz->methods;
495 method_annotations = annotation_bytearrays_insert(
496 method_annotations, slot, annotations);
498 if (method_annotations == NULL) {
502 LLNI_classinfo_field_set(
503 m->clazz, method_annotations, method_annotations);
510 /* annotation_load_method_attribute_runtimeinvisibleannotations ****************
512 Load runtime invisible annotations of a method (just skip them).
515 cb........the classbuffer from which the attribute has to be loaded.
516 m.........the method of which the runtime invisible annotations have
520 true if all went good. false otherwhise.
522 *******************************************************************************/
524 bool annotation_load_method_attribute_runtimeinvisibleannotations(
525 classbuffer *cb, methodinfo *m)
527 return loader_skip_attribute_body(cb);
531 /* annotation_load_field_attribute_runtimevisibleannotations ******************
533 Load runtime visible annotations of a field.
536 cb........the classbuffer from which the attribute has to be loaded.
537 f.........the field of which the runtime visible annotations have
541 true if all went good. false otherwhise.
543 *******************************************************************************/
545 bool annotation_load_field_attribute_runtimevisibleannotations(
546 classbuffer *cb, fieldinfo *f)
549 /* slot of the field */
550 java_handle_bytearray_t *annotations = NULL;
551 /* unparsed annotations */
552 java_handle_t *field_annotations = NULL;
553 /* array of unparsed field annotations */
558 LLNI_classinfo_field_get(
559 f->clazz, field_annotations, field_annotations);
561 if (!annotation_load_attribute_body(
563 "invalid runtime visible annotations field attribute")) {
567 if (annotations != NULL) {
568 slot = f - f->clazz->fields;
569 field_annotations = annotation_bytearrays_insert(
570 field_annotations, slot, annotations);
572 if (field_annotations == NULL) {
576 LLNI_classinfo_field_set(
577 f->clazz, field_annotations, field_annotations);
584 /* annotation_load_field_attribute_runtimeinvisibleannotations ****************
586 Load runtime invisible annotations of a field (just skip them).
589 cb........the classbuffer from which the attribute has to be loaded.
590 f.........the field of which the runtime invisible annotations have
594 true if all went good. false otherwhise.
596 *******************************************************************************/
598 bool annotation_load_field_attribute_runtimeinvisibleannotations(
599 classbuffer *cb, fieldinfo *f)
601 return loader_skip_attribute_body(cb);
606 * These are local overrides for various environment variables in Emacs.
607 * Please do not remove this and leave it at the end of the file, where
608 * Emacs will automagically detect them.
609 * ---------------------------------------------------------------------
612 * indent-tabs-mode: t
616 * vim:noexpandtab:sw=4:ts=4: