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