a266b4aa49daf3f5a44f28ccb5426bfc5c77bdc8
[cacao.git] / src / vmcore / annotation.c
1 /* src/vmcore/annotation.c - class annotations
2
3    Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id$
26
27 */
28
29 #include "config.h"
30
31 #include <assert.h>
32
33 #include "vm/types.h"
34
35 #include "mm/memory.h"
36
37 #include "toolbox/logging.h"
38
39 #include "vmcore/annotation.h"
40 #include "vmcore/class.h"
41 #include "vmcore/suck.h"
42
43 #if !defined(ENABLE_ANNOTATIONS)
44 # error annotation support has to be enabled when compling this file!
45 #endif
46
47 /* annotation_bytearray_new ***************************************************
48
49    Allocate a new bytearray.
50
51 *******************************************************************************/
52
53 annotation_bytearray_t *annotation_bytearray_new(uint32_t size)
54 {
55         annotation_bytearray_t *ba =
56                 mem_alloc(sizeof(uint32_t) + sizeof(uint8_t) * size);
57
58         if (ba != NULL) {
59                 ba->size = size;
60         }
61
62         return ba;
63 }
64
65
66 /* annotation_bytearray_free **************************************************
67
68    Free a bytearray.
69
70 *******************************************************************************/
71
72 void annotation_bytearray_free(annotation_bytearray_t *ba)
73 {
74         if (ba != NULL) {
75                 mem_free(ba, sizeof(uint32_t) + sizeof(uint8_t) * ba->size);
76         }
77 }
78
79
80 /* annotation_bytearrays_new **************************************************
81
82    Allocate a new array of bytearrays.
83
84 *******************************************************************************/
85
86 annotation_bytearrays_t *annotation_bytearrays_new(uint32_t size)
87 {
88         annotation_bytearrays_t *bas =
89                 mem_alloc(sizeof(uint32_t) + sizeof(annotation_bytearray_t*) * size);
90
91         if (bas != NULL) {
92                 bas->size = size;
93         }
94
95         return bas;
96 }
97
98
99 /* annotation_bytearrays_resize ***********************************************
100
101    Resize an array of bytearrays.
102
103 *******************************************************************************/
104
105 bool annotation_bytearrays_resize(annotation_bytearrays_t **bas,
106         uint32_t size)
107 {
108         annotation_bytearrays_t *newbas = NULL;
109         uint32_t i;
110         uint32_t minsize;
111         
112         assert(bas != NULL);
113         
114         newbas = annotation_bytearrays_new(size);
115         
116         if (newbas == NULL) {
117                 return false;
118         }
119         
120         if (*bas != NULL) {
121                 minsize = size < (*bas)->size ? size : (*bas)->size;
122
123                 for (i = size; i < (*bas)->size; ++ i) {
124                         annotation_bytearray_free((*bas)->data[i]);
125                 }
126
127                 for (i = 0; i < minsize; ++i) {
128                         newbas->data[i] = (*bas)->data[i];
129                 }
130         }
131
132         *bas = newbas;
133
134         return true;
135 }
136
137
138 /* annotation_bytearrays_insert ***********************************************
139
140    Insert a bytearray into an array of bytearrays.
141
142 *******************************************************************************/
143
144 bool annotation_bytearrays_insert(annotation_bytearrays_t **bas,
145         uint32_t index, annotation_bytearray_t *ba)
146 {
147         assert(bas != NULL);
148
149         if (ba != NULL) {
150                 if (*bas == NULL || (*bas)->size <= index) {
151                         if (!annotation_bytearrays_resize(bas, index + 1)) {
152                                 return false;
153                         }
154                 }
155                 else {
156                         /* free old bytearray (if any) */
157                         annotation_bytearray_free((*bas)->data[index]);
158                 }
159
160                 /* insert new bytearray */
161                 (*bas)->data[index] = ba;
162         }
163         else if (*bas != NULL && (*bas)->size > index) {
164                 /* do not resize when just inserting NULL,
165                  * but free old bytearray if there is any */
166                 annotation_bytearray_free((*bas)->data[index]);
167         }
168
169         return true;
170 }
171
172
173 /* annotation_bytearrays_free *************************************************
174
175    Free an array of bytearrays.
176
177 *******************************************************************************/
178
179 void annotation_bytearrays_free(annotation_bytearrays_t *bas)
180 {
181         uint32_t i;
182
183         if (bas != NULL) {
184                 for (i = 0; i < bas->size; ++ i) {
185                         annotation_bytearray_free(bas->data[i]);
186                 }
187
188                 mem_free(bas, sizeof(uint32_t) +
189                         sizeof(annotation_bytearray_t*) * bas->size);
190         }
191 }
192
193
194 /* annotation_load_attribute_body *********************************************
195
196    This function loads the body of a generic attribute.
197
198    XXX: Maybe this function should be called loader_load_attribute_body and
199         located in vmcore/loader.c?
200
201    attribute_info {
202        u2 attribute_name_index;
203        u4 attribute_length;
204        u1 info[attribute_length];
205    }
206
207    IN:
208        cb.................classbuffer from which to read the data.
209        errormsg_prefix....prefix for error messages (if any).
210
211    OUT:
212        attribute..........bytearray-pointer which will be set to the read data.
213    
214    RETURN VALUE:
215        true if all went good. false otherwhise.
216
217 *******************************************************************************/
218
219 static bool annotation_load_attribute_body(classbuffer *cb,
220         annotation_bytearray_t **attribute, const char *errormsg_prefix)
221 {
222         uint32_t size = 0;
223         annotation_bytearray_t *ba = NULL;
224
225         assert(cb != NULL);
226         assert(attribute != NULL);
227
228         if (!suck_check_classbuffer_size(cb, 4)) {
229                 log_println("%s: size missing", errormsg_prefix);
230                 return false;
231         }
232
233         /* load attribute_length */
234         size = suck_u4(cb);
235         
236         if (!suck_check_classbuffer_size(cb, size)) {
237                 log_println("%s: invalid size", errormsg_prefix);
238                 return false;
239         }
240         
241         /* if attribute_length == 0 then NULL is
242          * the right value for this attribute */
243         if (size > 0) {
244                 ba = annotation_bytearray_new(size);
245
246                 if (ba == NULL) {
247                         /* out of memory */
248                         return false;
249                 }
250
251                 /* load data */
252                 suck_nbytes(ba->data, cb, size);
253
254                 /* return data */
255                 *attribute = ba;
256         }
257         
258         return true;
259 }
260
261
262 /* annotation_load_method_attribute_annotationdefault *************************
263
264    Load annotation default value.
265
266    AnnotationDefault_attribute {
267        u2 attribute_name_index;
268        u4 attribute_length;
269        element_value default_value;
270    }
271
272    IN:
273        cb.................classbuffer from which to read the data.
274        m..................methodinfo for the method of which the annotation
275                           default value is read and into which the value is
276                           stored into.
277
278    RETURN VALUE:
279        true if all went good. false otherwhise.
280
281 *******************************************************************************/
282
283 bool annotation_load_method_attribute_annotationdefault(
284                 classbuffer *cb, methodinfo *m)
285 {
286         int slot = 0;
287         annotation_bytearray_t   *annotationdefault  = NULL;
288         annotation_bytearrays_t **annotationdefaults = NULL;
289
290         assert(cb != NULL);
291         assert(m != NULL);
292
293         annotationdefaults = &(m->class->method_annotationdefaults);
294
295         if (!annotation_load_attribute_body(
296                 cb, &annotationdefault,
297                 "invalid annotation default method attribute")) {
298                 return false;
299         }
300
301         if (annotationdefault != NULL) {
302                 slot = m - m->class->methods;
303
304                 if (!annotation_bytearrays_insert(
305                         annotationdefaults, slot, annotationdefault)) {
306                         annotation_bytearray_free(annotationdefault);
307                         return false;
308                 }
309         }
310
311         return true;
312 }
313
314
315 /* annotation_load_method_attribute_runtimevisibleparameterannotations ********
316
317    Load runtime visible parameter annotations.
318
319    RuntimeVisibleParameterAnnotations_attribute {
320        u2 attribute_name_index;
321        u4 attribute_length;
322        u1 num_parameters;
323        {
324            u2 num_annotations;
325            annotation annotations[num_annotations];
326        } parameter_annotations[num_parameters];
327    }
328
329    IN:
330        cb.................classbuffer from which to read the data.
331        m..................methodinfo for the method of which the parameter
332                           annotations are read and into which the parameter
333                           annotations are stored into.
334
335    RETURN VALUE:
336        true if all went good. false otherwhise.
337
338 *******************************************************************************/
339
340 bool annotation_load_method_attribute_runtimevisibleparameterannotations(
341                 classbuffer *cb, methodinfo *m)
342 {
343         int slot = 0;
344         annotation_bytearray_t  *annotations = NULL;
345         annotation_bytearrays_t **parameterannotations = NULL;
346
347         assert(cb != NULL);
348         assert(m != NULL);
349
350         parameterannotations = &(m->class->method_parameterannotations);
351
352         if (!annotation_load_attribute_body(
353                 cb, &annotations,
354                 "invalid runtime visible parameter annotations method attribute")) {
355                 return false;
356         }
357
358         if (annotations != NULL) {
359                 slot = m - m->class->methods;
360
361                 if (!annotation_bytearrays_insert(
362                         parameterannotations, slot, annotations)) {
363                         annotation_bytearray_free(annotations);
364                         return false;
365                 }
366         }
367
368         return true;
369 }
370
371
372 /* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
373  
374    Load runtime invisible parameter annotations.
375
376    <quote cite="http://jcp.org/en/jsr/detail?id=202">
377    The RuntimeInvisibleParameterAnnotations attribute is similar to the
378    RuntimeVisibleParameterAnnotations attribute, except that the annotations
379    represented by a RuntimeInvisibleParameterAnnotations attribute must not be
380    made available for return by reflective APIs, unless the the JVM has
381    specifically been instructed to retain these annotations via some
382    implementation-specific mechanism such as a command line flag. In the
383    absence of such instructions, the JVM ignores this attribute.
384    </quote>
385
386    Hotspot loads them into the same bytearray as the runtime visible parameter
387    annotations (after the runtime visible parameter annotations). But in J2SE
388    the bytearray will only be parsed as if ther is only one annotation
389    structure in it, so the runtime invisible parameter annotatios will be
390    ignored.
391
392    Therefore I do not even bother to read them.
393
394    RuntimeInvisibleParameterAnnotations_attribute {
395        u2 attribute_name_index;
396        u4 attribute_length;
397        u1 num_parameters;
398        {
399            u2 num_annotations;
400            annotation annotations[num_annotations];
401        } parameter_annotations[num_parameters];
402    }
403
404    IN:
405        cb.................classbuffer from which to read the data.
406        m..................methodinfo for the method of which the parameter
407                           annotations are read and into which the parameter
408                           annotations are stored into.
409
410    RETURN VALUE:
411        true if all went good. false otherwhise.
412
413 *******************************************************************************/
414
415 bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
416                 classbuffer *cb, methodinfo *m)
417 {
418         return loader_skip_attribute_body(cb);
419 }
420
421
422 /* annotation_load_class_attribute_runtimevisibleannotations ******************
423    
424    Load runtime visible annotations of a class.
425    
426 *******************************************************************************/
427
428 bool annotation_load_class_attribute_runtimevisibleannotations(
429         classbuffer *cb)
430 {
431         return annotation_load_attribute_body(
432                 cb, &(cb->class->annotations),
433                 "invalid runtime visible annotations class attribute");
434 }
435
436
437 /* annotation_load_class_attribute_runtimeinvisibleannotations ****************
438    
439    Load runtime invisible annotations of a class (just skip them).
440    
441 *******************************************************************************/
442
443 bool annotation_load_class_attribute_runtimeinvisibleannotations(
444         classbuffer *cb)
445 {
446         return loader_skip_attribute_body(cb);
447 }
448
449
450 /* annotation_load_method_attribute_runtimevisibleannotations *****************
451    
452    Load runtime visible annotations of a method.
453    
454 *******************************************************************************/
455
456 bool annotation_load_method_attribute_runtimevisibleannotations(
457         classbuffer *cb, methodinfo *m)
458 {
459         int slot = 0;
460         annotation_bytearray_t  *annotations = NULL;
461         annotation_bytearrays_t **method_annotations = NULL;
462
463         assert(cb != NULL);
464         assert(m != NULL);
465
466         method_annotations = &(m->class->method_annotations);
467
468         if (!annotation_load_attribute_body(
469                 cb, &annotations,
470                 "invalid runtime visible annotations method attribute")) {
471                 return false;
472         }
473
474         if (annotations != NULL) {
475                 slot = m - m->class->methods;
476
477                 if (!annotation_bytearrays_insert(
478                         method_annotations, slot, annotations)) {
479                         annotation_bytearray_free(annotations);
480                         return false;
481                 }
482         }
483
484         return true;
485 }
486
487
488 /* annotation_load_method_attribute_runtimeinvisibleannotations ****************
489    
490    Load runtime invisible annotations of a method (just skip them).
491    
492 *******************************************************************************/
493
494 bool annotation_load_method_attribute_runtimeinvisibleannotations(
495         classbuffer *cb, methodinfo *m)
496 {
497         return loader_skip_attribute_body(cb);
498 }
499
500
501 /* annotation_load_field_attribute_runtimevisibleannotations ******************
502    
503    Load runtime visible annotations of a field.
504    
505 *******************************************************************************/
506
507 bool annotation_load_field_attribute_runtimevisibleannotations(
508         classbuffer *cb, fieldinfo *f)
509 {
510         int slot = 0;
511         annotation_bytearray_t  *annotations = NULL;
512         annotation_bytearrays_t **field_annotations = NULL;
513
514         assert(cb != NULL);
515         assert(f != NULL);
516
517         field_annotations = &(f->class->field_annotations);
518
519         if (!annotation_load_attribute_body(
520                 cb, &annotations,
521                 "invalid runtime visible annotations field attribute")) {
522                 return false;
523         }
524
525         if (annotations != NULL) {
526                 slot = f - f->class->fields;
527
528                 if (!annotation_bytearrays_insert(
529                         field_annotations, slot, annotations)) {
530                         annotation_bytearray_free(annotations);
531                         return false;
532                 }
533         }
534
535         return true;
536 }
537
538
539 /* annotation_load_field_attribute_runtimeinvisibleannotations ****************
540    
541    Load runtime invisible annotations of a field (just skip them).
542    
543 *******************************************************************************/
544
545 bool annotation_load_field_attribute_runtimeinvisibleannotations(
546         classbuffer *cb, fieldinfo *f)
547 {
548         return loader_skip_attribute_body(cb);
549 }
550
551
552 /*
553  * These are local overrides for various environment variables in Emacs.
554  * Please do not remove this and leave it at the end of the file, where
555  * Emacs will automagically detect them.
556  * ---------------------------------------------------------------------
557  * Local variables:
558  * mode: c
559  * indent-tabs-mode: t
560  * c-basic-offset: 4
561  * tab-width: 4
562  * End:
563  * vim:noexpandtab:sw=4:ts=4:
564  */