Line data Source code
1 : /* src/vm/annotation.cpp - class annotations
2 :
3 : Copyright (C) 2006-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
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.
12 :
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.
17 :
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
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 :
26 : #include "config.h"
27 :
28 : #include <assert.h>
29 : #include <stdint.h>
30 :
31 : #include "native/llni.hpp"
32 :
33 : #include "mm/memory.hpp"
34 :
35 : #include "toolbox/logging.hpp"
36 :
37 : #include "vm/annotation.hpp"
38 : #include "vm/array.hpp"
39 : #include "vm/jit/builtin.hpp"
40 : #include "vm/class.hpp"
41 : #include "vm/field.hpp"
42 : #include "vm/loader.hpp"
43 : #include "vm/method.hpp"
44 : #include "vm/primitive.hpp"
45 : #include "vm/suck.hpp"
46 : #include "vm/types.hpp"
47 :
48 : #if !defined(ENABLE_ANNOTATIONS)
49 : # error annotation support has to be enabled when compling this file!
50 : #endif
51 :
52 : namespace cacao {
53 :
54 : /* annotation_bytearrays_resize ***********************************************
55 :
56 : Resize an array of bytearrays.
57 :
58 : IN:
59 : bytearrays.....array of bytearrays
60 : size...........new size of the refered array
61 :
62 : RETURN VALUE:
63 : The new array if a resize was neccessarry, the old if the given size
64 : equals the current size or NULL if an error occured.
65 :
66 : *******************************************************************************/
67 :
68 271 : static java_handle_objectarray_t *annotation_bytearrays_resize(
69 : java_handle_objectarray_t *bytearrays, uint32_t size)
70 : {
71 271 : uint32_t minsize = 0; /* count of object refs to copy */
72 271 : uint32_t oldsize = 0; /* size of old array */
73 :
74 271 : ObjectArray bas(bytearrays);
75 :
76 271 : if (bytearrays != NULL) {
77 87 : oldsize = bas.get_length();
78 :
79 : /* if the size already fits do nothing */
80 87 : if (size == oldsize) {
81 0 : return bytearrays;
82 : }
83 : }
84 :
85 : // Allocate new array on the heap.
86 :
87 : ObjectArray newbas(size,
88 271 : Primitive::get_arrayclass_by_type(PRIMITIVETYPE_BYTE));
89 :
90 : /* is there a old byte array array? */
91 271 : if (newbas.is_non_null() && bytearrays != NULL) {
92 87 : minsize = size < oldsize ? size : oldsize;
93 :
94 : LLNI_CRITICAL_START;
95 : MCOPY(
96 : newbas.get_raw_data_ptr(), bas.get_raw_data_ptr(),
97 87 : java_object_t*, minsize);
98 : LLNI_CRITICAL_END;
99 : }
100 :
101 271 : return newbas.get_handle();
102 : }
103 :
104 :
105 : /* annotation_bytearrays_insert ***********************************************
106 :
107 : Insert a bytearray into an array of bytearrays.
108 :
109 : IN:
110 : bytearrays........array of bytearrays where 'bytearray' has to be
111 : inserted at position 'index'.
112 : index.............position where 'ba' has to be inserted into
113 : 'bytearrays'.
114 : bytearray.........byte array which has to be inserted into
115 : 'bytearrays'.
116 :
117 : RETURN VALUE:
118 : The new array if a resize was neccessarry, the old if the given size
119 : equals the current size or NULL if an error occured.
120 :
121 : *******************************************************************************/
122 :
123 271 : static java_handle_t *annotation_bytearrays_insert(
124 : java_handle_t *bytearrays, uint32_t index,
125 : java_handle_bytearray_t *bytearray)
126 : {
127 271 : uint32_t size = 0; /* current size of the array */
128 :
129 : /* do nothing if NULL is inserted but no array exists */
130 271 : if (bytearray == NULL && bytearrays == NULL) {
131 0 : return NULL;
132 : }
133 :
134 271 : ObjectArray bas(bytearrays);
135 :
136 : /* get lengths if array exists */
137 271 : if (bytearrays != NULL) {
138 87 : size = bas.get_length();
139 : }
140 :
141 271 : if (bytearray == NULL) {
142 : /* insert NULL only if array is big enough */
143 0 : if (size > index) {
144 0 : bas.set_element(index, NULL);
145 : }
146 : }
147 : else {
148 : // XXX: We should use a clone function here!!!
149 : /* resize array if it's not enough for inserted value */
150 271 : if (size <= index) {
151 271 : bas = annotation_bytearrays_resize(bas.get_handle(), index + 1);
152 :
153 271 : if (bas.is_null()) {
154 : /* out of memory */
155 0 : return NULL;
156 : }
157 : }
158 :
159 271 : bas.set_element(index, (java_handle_t*) bytearray);
160 : }
161 :
162 271 : return bas.get_handle();
163 : }
164 :
165 :
166 : /* annotation_load_attribute_body *********************************************
167 :
168 : This function loads the body of a generic attribute.
169 :
170 : XXX: Maybe this function should be called loader_load_attribute_body and
171 : located in vm/loader.c?
172 :
173 : attribute_info {
174 : u2 attribute_name_index;
175 : u4 attribute_length;
176 : u1 info[attribute_length];
177 : }
178 :
179 : IN:
180 : cb.................classbuffer from which to read the data.
181 : errormsg_prefix....prefix for error messages (if any).
182 :
183 : OUT:
184 : attribute..........bytearray-pointer which will be set to the read data.
185 :
186 : RETURN VALUE:
187 : true if all went good. false otherwhise.
188 :
189 : *******************************************************************************/
190 :
191 311 : static bool annotation_load_attribute_body(ClassBuffer& cb,
192 : java_handle_bytearray_t **attribute,
193 : const char *errormsg_prefix) {
194 311 : assert(cb);
195 311 : assert(attribute != NULL);
196 :
197 311 : if (!cb.check_size(4)) {
198 0 : log_println("%s: size missing", errormsg_prefix);
199 0 : return false;
200 : }
201 :
202 : /* load attribute_length */
203 311 : uint32_t size = cb.read_u4();
204 :
205 311 : if (!cb.check_size(size)) {
206 0 : log_println("%s: invalid size", errormsg_prefix);
207 0 : return false;
208 : }
209 :
210 : /* if attribute_length == 0 then NULL is
211 : * the right value for this attribute */
212 311 : if (size > 0) {
213 311 : ByteArray ba(size);
214 :
215 311 : if (ba.is_null()) {
216 : /* out of memory */
217 0 : return false;
218 : }
219 :
220 : /* load data */
221 : LLNI_CRITICAL_START;
222 :
223 311 : uint8_t* ptr = (uint8_t*) ba.get_raw_data_ptr();
224 311 : cb.read_nbytes(ptr, size);
225 :
226 : LLNI_CRITICAL_END;
227 :
228 : /* return data */
229 311 : *attribute = ba.get_handle();
230 : }
231 :
232 311 : return true;
233 : }
234 :
235 :
236 : /* annotation_load_method_attribute_annotationdefault *************************
237 :
238 : Load annotation default value.
239 :
240 : AnnotationDefault_attribute {
241 : u2 attribute_name_index;
242 : u4 attribute_length;
243 : element_value default_value;
244 : }
245 :
246 : IN:
247 : cb.................classbuffer from which to read the data.
248 : m..................methodinfo for the method of which the annotation
249 : default value is read and into which the value is
250 : stored into.
251 :
252 : RETURN VALUE:
253 : true if all went good. false otherwhise.
254 :
255 : *******************************************************************************/
256 :
257 31 : bool annotation_load_method_attribute_annotationdefault(ClassBuffer& cb, methodinfo *m) {
258 31 : int slot = 0; // the slot of the method
259 31 : java_handle_bytearray_t *annotationdefault = NULL; // unparsed annotation defalut value
260 31 : java_handle_t *annotationdefaults = NULL; // array of unparsed annotation default values
261 :
262 31 : assert(cb);
263 31 : assert(m != NULL);
264 :
265 31 : LLNI_classinfo_field_get(m->clazz,
266 : method_annotationdefaults,
267 : annotationdefaults);
268 :
269 31 : if (!annotation_load_attribute_body(cb,
270 : &annotationdefault,
271 : "invalid annotation default method attribute"))
272 0 : return false;
273 :
274 31 : if (annotationdefault != NULL) {
275 31 : slot = m - m->clazz->methods;
276 : annotationdefaults = annotation_bytearrays_insert(
277 31 : annotationdefaults, slot, annotationdefault);
278 :
279 31 : if (annotationdefaults == NULL) {
280 0 : return false;
281 : }
282 :
283 31 : LLNI_classinfo_field_set(
284 : m->clazz, method_annotationdefaults, annotationdefaults);
285 : }
286 :
287 31 : return true;
288 : }
289 :
290 :
291 : /* annotation_load_method_attribute_runtimevisibleparameterannotations ********
292 :
293 : Load runtime visible parameter annotations.
294 :
295 : RuntimeVisibleParameterAnnotations_attribute {
296 : u2 attribute_name_index;
297 : u4 attribute_length;
298 : u1 num_parameters;
299 : {
300 : u2 num_annotations;
301 : annotation annotations[num_annotations];
302 : } parameter_annotations[num_parameters];
303 : }
304 :
305 : IN:
306 : cb.................classbuffer from which to read the data.
307 : m..................methodinfo for the method of which the parameter
308 : annotations are read and into which the parameter
309 : annotations are stored into.
310 :
311 : RETURN VALUE:
312 : true if all went good. false otherwhise.
313 :
314 : *******************************************************************************/
315 :
316 2 : bool annotation_load_method_attribute_runtimevisibleparameterannotations(ClassBuffer& cb,
317 : methodinfo *m) {
318 2 : int slot = 0; // the slot of the method
319 2 : java_handle_bytearray_t *annotations = NULL; // unparsed parameter annotations
320 2 : java_handle_t *parameterannotations = NULL; // array of unparsed parameter annotations
321 :
322 2 : assert(cb);
323 2 : assert(m != NULL);
324 :
325 2 : LLNI_classinfo_field_get(m->clazz,
326 : method_parameterannotations,
327 : parameterannotations);
328 :
329 2 : if (!annotation_load_attribute_body(cb,
330 : &annotations,
331 : "invalid runtime visible parameter annotations method attribute"))
332 0 : return false;
333 :
334 2 : if (annotations != NULL) {
335 2 : slot = m - m->clazz->methods;
336 : parameterannotations = annotation_bytearrays_insert(
337 2 : parameterannotations, slot, annotations);
338 :
339 2 : if (parameterannotations == NULL) {
340 0 : return false;
341 : }
342 :
343 2 : LLNI_classinfo_field_set(
344 : m->clazz, method_parameterannotations, parameterannotations);
345 : }
346 :
347 2 : return true;
348 : }
349 :
350 :
351 : /* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
352 :
353 : Load runtime invisible parameter annotations.
354 :
355 : <quote cite="http://jcp.org/en/jsr/detail?id=202">
356 : The RuntimeInvisibleParameterAnnotations attribute is similar to the
357 : RuntimeVisibleParameterAnnotations attribute, except that the annotations
358 : represented by a RuntimeInvisibleParameterAnnotations attribute must not be
359 : made available for return by reflective APIs, unless the the JVM has
360 : specifically been instructed to retain these annotations via some
361 : implementation-specific mechanism such as a command line flag. In the
362 : absence of such instructions, the JVM ignores this attribute.
363 : </quote>
364 :
365 : Hotspot loads them into the same bytearray as the runtime visible parameter
366 : annotations (after the runtime visible parameter annotations). But in J2SE
367 : the bytearray will only be parsed as if there is only one annotation
368 : structure in it, so the runtime invisible parameter annotatios will be
369 : ignored.
370 :
371 : Therefore I do not even bother to read them.
372 :
373 : RuntimeInvisibleParameterAnnotations_attribute {
374 : u2 attribute_name_index;
375 : u4 attribute_length;
376 : u1 num_parameters;
377 : {
378 : u2 num_annotations;
379 : annotation annotations[num_annotations];
380 : } parameter_annotations[num_parameters];
381 : }
382 :
383 : IN:
384 : cb.................classbuffer from which to read the data.
385 : m..................methodinfo for the method of which the parameter
386 : annotations are read and into which the parameter
387 : annotations are stored into.
388 :
389 : RETURN VALUE:
390 : true if all went good. false otherwhise.
391 :
392 : *******************************************************************************/
393 :
394 0 : bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(ClassBuffer& cb,
395 : methodinfo *m) {
396 0 : return loader_skip_attribute_body(cb);
397 : }
398 :
399 :
400 : /* annotation_load_class_attribute_runtimevisibleannotations ******************
401 :
402 : Load runtime visible annotations of a class.
403 :
404 : IN:
405 : cb........the classbuffer from which the attribute has to be loaded.
406 :
407 : RETURN VALUE:
408 : true if all went good. false otherwhise.
409 :
410 : *******************************************************************************/
411 :
412 40 : bool annotation_load_class_attribute_runtimevisibleannotations(ClassBuffer& cb) {
413 40 : java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
414 :
415 40 : if (!annotation_load_attribute_body(
416 : cb, &annotations,
417 : "invalid runtime visible annotations class attribute")) {
418 0 : return false;
419 : }
420 :
421 40 : LLNI_classinfo_field_set(cb.get_class(), annotations, (java_handle_t*)annotations);
422 :
423 40 : return true;
424 : }
425 :
426 :
427 : /* annotation_load_class_attribute_runtimeinvisibleannotations ****************
428 :
429 : Load runtime invisible annotations of a class (just skip them).
430 :
431 : IN:
432 : cb........the classbuffer from which the attribute has to be loaded.
433 :
434 : RETURN VALUE:
435 : true if all went good. false otherwhise.
436 :
437 : *******************************************************************************/
438 :
439 1 : bool annotation_load_class_attribute_runtimeinvisibleannotations(ClassBuffer& cb) {
440 1 : return loader_skip_attribute_body(cb);
441 : }
442 :
443 :
444 : /* annotation_load_method_attribute_runtimevisibleannotations *****************
445 :
446 : Load runtime visible annotations of a method.
447 :
448 : IN:
449 : cb........the classbuffer from which the attribute has to be loaded.
450 : m.........the method of which the runtime visible annotations have
451 : to be loaded.
452 :
453 : RETURN VALUE:
454 : true if all went good. false otherwhise.
455 :
456 : *******************************************************************************/
457 :
458 236 : bool annotation_load_method_attribute_runtimevisibleannotations(ClassBuffer& cb,
459 : methodinfo *m) {
460 236 : int slot = 0; // slot of the method
461 236 : java_handle_bytearray_t *annotations = NULL; // unparsed annotations
462 236 : java_handle_t *method_annotations = NULL; // array of unparsed method annotations */
463 :
464 236 : assert(cb);
465 236 : assert(m != NULL);
466 :
467 236 : LLNI_classinfo_field_get(
468 : m->clazz, method_annotations, method_annotations);
469 :
470 236 : if (!annotation_load_attribute_body(
471 : cb, &annotations,
472 : "invalid runtime visible annotations method attribute")) {
473 0 : return false;
474 : }
475 :
476 236 : if (annotations != NULL) {
477 236 : slot = m - m->clazz->methods;
478 : method_annotations = annotation_bytearrays_insert(
479 236 : method_annotations, slot, annotations);
480 :
481 236 : if (method_annotations == NULL) {
482 0 : return false;
483 : }
484 :
485 236 : LLNI_classinfo_field_set(
486 : m->clazz, method_annotations, method_annotations);
487 : }
488 :
489 236 : return true;
490 : }
491 :
492 :
493 : /* annotation_load_method_attribute_runtimeinvisibleannotations ****************
494 :
495 : Load runtime invisible annotations of a method (just skip them).
496 :
497 : IN:
498 : cb........the classbuffer from which the attribute has to be loaded.
499 : m.........the method of which the runtime invisible annotations have
500 : to be loaded.
501 :
502 : RETURN VALUE:
503 : true if all went good. false otherwhise.
504 :
505 : *******************************************************************************/
506 :
507 0 : bool annotation_load_method_attribute_runtimeinvisibleannotations(ClassBuffer& cb,
508 : methodinfo *m) {
509 0 : return loader_skip_attribute_body(cb);
510 : }
511 :
512 :
513 : /* annotation_load_field_attribute_runtimevisibleannotations ******************
514 :
515 : Load runtime visible annotations of a field.
516 :
517 : IN:
518 : cb........the classbuffer from which the attribute has to be loaded.
519 : f.........the field of which the runtime visible annotations have
520 : to be loaded.
521 :
522 : RETURN VALUE:
523 : true if all went good. false otherwhise.
524 :
525 : *******************************************************************************/
526 :
527 2 : bool annotation_load_field_attribute_runtimevisibleannotations(ClassBuffer& cb,
528 : fieldinfo *f) {
529 2 : int slot = 0; // slot of the field
530 2 : java_handle_bytearray_t *annotations = NULL; // unparsed annotations
531 2 : java_handle_t *field_annotations = NULL; // array of unparsed field annotations
532 :
533 2 : assert(cb);
534 2 : assert(f != NULL);
535 :
536 2 : LLNI_classinfo_field_get(
537 : f->clazz, field_annotations, field_annotations);
538 :
539 2 : if (!annotation_load_attribute_body(
540 : cb, &annotations,
541 : "invalid runtime visible annotations field attribute")) {
542 0 : return false;
543 : }
544 :
545 2 : if (annotations != NULL) {
546 2 : slot = f - f->clazz->fields;
547 : field_annotations = annotation_bytearrays_insert(
548 2 : field_annotations, slot, annotations);
549 :
550 2 : if (field_annotations == NULL) {
551 0 : return false;
552 : }
553 :
554 2 : LLNI_classinfo_field_set(
555 : f->clazz, field_annotations, field_annotations);
556 : }
557 :
558 2 : return true;
559 : }
560 :
561 :
562 : /* annotation_load_field_attribute_runtimeinvisibleannotations ****************
563 :
564 : Load runtime invisible annotations of a field (just skip them).
565 :
566 : IN:
567 : cb........the classbuffer from which the attribute has to be loaded.
568 : f.........the field of which the runtime invisible annotations have
569 : to be loaded.
570 :
571 : RETURN VALUE:
572 : true if all went good. false otherwhise.
573 :
574 : *******************************************************************************/
575 :
576 0 : bool annotation_load_field_attribute_runtimeinvisibleannotations(ClassBuffer& cb,
577 : fieldinfo *f) {
578 0 : return loader_skip_attribute_body(cb);
579 : }
580 :
581 : } // end namespace cacao;
582 :
583 : /*
584 : * These are local overrides for various environment variables in Emacs.
585 : * Please do not remove this and leave it at the end of the file, where
586 : * Emacs will automagically detect them.
587 : * ---------------------------------------------------------------------
588 : * Local variables:
589 : * mode: c++
590 : * indent-tabs-mode: t
591 : * c-basic-offset: 4
592 : * tab-width: 4
593 : * End:
594 : * vim:noexpandtab:sw=4:ts=4:
595 : */
|