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