LCOV - code coverage report
Current view: top level - vm - annotation.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 100 125 80.0 %
Date: 2017-07-14 10:03:36 Functions: 9 12 75.0 %

          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             :  */

Generated by: LCOV version 1.11