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