LCOV - code coverage report
Current view: top level - vm - field.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 87 179 48.6 %
Date: 2015-06-10 18:10:59 Functions: 3 9 33.3 %

          Line data    Source code
       1             : /* src/vm/field.cpp - field functions
       2             : 
       3             :    Copyright (C) 1996-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 <stdio.h>
      30             : 
      31             : #include "mm/memory.hpp"
      32             : 
      33             : #include "native/llni.hpp"
      34             : 
      35             : #include "vm/types.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/descriptor.hpp"
      42             : #include "vm/exceptions.hpp"
      43             : #include "vm/field.hpp"
      44             : #include "vm/global.hpp"
      45             : #include "vm/globals.hpp"
      46             : #include "vm/loader.hpp"
      47             : #include "vm/options.hpp"
      48             : #include "vm/primitive.hpp"
      49             : #include "vm/references.hpp"
      50             : #include "vm/string.hpp"
      51             : #include "vm/suck.hpp"
      52             : #include "vm/utf8.hpp"
      53             : #include "vm/vm.hpp"
      54             : 
      55             : using namespace cacao;
      56             : 
      57             : /* field_load ******************************************************************
      58             : 
      59             :    Load everything about a class field from the class file and fill a
      60             :    fieldinfo structure.
      61             : 
      62             : *******************************************************************************/
      63             : 
      64             : #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
      65             : 
      66      113368 : bool field_load(ClassBuffer& cb, fieldinfo *f, DescriptorPool& descpool)
      67             : {
      68             :         u4 attrnum, i;
      69      113368 :         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
      70      113368 :         Utf8String u;
      71             : 
      72             :         /* Get class. */
      73             : 
      74      113368 :         classinfo *c = cb.get_class();
      75             : 
      76      113368 :         f->clazz = c;
      77             : 
      78             :         /* Get access flags. */
      79             : 
      80      113368 :         if (!cb.check_size(2 + 2 + 2))
      81           0 :                 return false;
      82             : 
      83      113368 :         f->flags = cb.read_u2();
      84             : 
      85             :         /* Get name. */
      86             : 
      87      113368 :         if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
      88           0 :                 return false;
      89             : 
      90      113368 :         f->name = u;
      91             : 
      92             :         /* Get descriptor. */
      93             : 
      94      113368 :         if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
      95           0 :                 return false;
      96             : 
      97      113368 :         f->descriptor = u;
      98      113368 :         f->parseddesc = NULL;
      99             : 
     100      113368 :         if (!descpool.add_field(u))
     101           0 :                 return false;
     102             : 
     103             :         /* descriptor_pool_add accepts method descriptors, so we have to
     104             :            check against them here before the call of
     105             :            descriptor_to_basic_type below. */
     106             : 
     107      113368 :         if (u[0] == '(') {
     108           0 :                 exceptions_throw_classformaterror(c, "Method descriptor used for field");
     109           0 :                 return false;
     110             :         }
     111             : 
     112             : #ifdef ENABLE_VERIFIER
     113      113368 :         if (opt_verify) {
     114             :                 /* check name */
     115      113368 :                 if (!f->name.is_valid_name() || f->name[0] == '<') {
     116             :                         exceptions_throw_classformaterror(c,
     117             :                                                           "Illegal Field name \"%s\"",
     118           0 :                                                           f->name.begin());
     119           0 :                         return false;
     120             :                 }
     121             : 
     122             :                 /* check flag consistency */
     123      113368 :                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
     124             : 
     125      113368 :                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
     126             :                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
     127             :                         exceptions_throw_classformaterror(c,
     128             :                                                                                           "Illegal field modifiers: 0x%X",
     129           0 :                                                                                           f->flags);
     130           0 :                         return false;
     131             :                 }
     132             : 
     133      113368 :                 if (c->flags & ACC_INTERFACE) {
     134        2770 :                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
     135             :                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
     136             :                                 f->flags & ACC_TRANSIENT) {
     137             :                                 exceptions_throw_classformaterror(c,
     138             :                                                                                                   "Illegal field modifiers: 0x%X",
     139           0 :                                                                                                   f->flags);
     140           0 :                                 return false;
     141             :                         }
     142             :                 }
     143             :         }
     144             : #endif /* ENABLE_VERIFIER */
     145             : 
     146             :         /* data type */
     147             : 
     148      113368 :         f->type = descriptor_to_basic_type(f->descriptor);
     149             : 
     150             :         /* For static-fields allocate memory for the value and set the
     151             :            value to 0. */
     152             : 
     153      113368 :         if (f->flags & ACC_STATIC) {
     154       61032 :                 switch (f->type) {
     155             :                 case TYPE_INT:
     156             :                 case TYPE_LNG:
     157             :                 case TYPE_FLT:
     158             :                 case TYPE_DBL:
     159       36335 :                         f->value = NEW(imm_union);
     160       36335 :                         break;
     161             : 
     162             :                 case TYPE_ADR:
     163             : #if !defined(ENABLE_GC_BOEHM)
     164             :                         f->value = NEW(imm_union);
     165             : #else
     166       24697 :                         f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
     167             : #endif
     168       24697 :                         break;
     169             : 
     170             :                 default:
     171           0 :                         vm_abort("field_load: invalid field type %d", f->type);
     172             :                 }
     173             : 
     174             :                 /* Set the field to zero, for float and double fields set the
     175             :                    correct 0.0 value. */
     176             : 
     177       61032 :                 switch (f->type) {
     178             :                 case TYPE_INT:
     179             :                 case TYPE_LNG:
     180             :                 case TYPE_ADR:
     181       58473 :                         f->value->l = 0;
     182       58473 :                         break;
     183             : 
     184             :                 case TYPE_FLT:
     185        1454 :                         f->value->f = 0.0;
     186        1454 :                         break;
     187             : 
     188             :                 case TYPE_DBL:
     189        1105 :                         f->value->d = 0.0;
     190             :                         break;
     191             :                 }
     192             :         }
     193             :         else {
     194             :                 /* For instance-fields set the offset to 0. */
     195             : 
     196       52336 :                 f->offset = 0;
     197             : 
     198             :                 /* For final fields, which are not static, we need a value
     199             :                    structure. */
     200             : 
     201       52336 :                 if (f->flags & ACC_FINAL) {
     202       16708 :                         f->value = NEW(imm_union);
     203             :                         /* XXX hack */
     204       16708 :                         f->value->l = 0;
     205             :                 }
     206             : 
     207       52336 :                 switch (f->type) {
     208             :                 case TYPE_ADR:
     209       31278 :                         c->flags |= ACC_CLASS_HAS_POINTERS;
     210             :                         break;
     211             :                 }
     212             :         }
     213             : 
     214             :         /* read attributes */
     215             : 
     216      113368 :         if (!cb.check_size(2))
     217           0 :                 return false;
     218             : 
     219      113368 :         attrnum = cb.read_u2();
     220             : 
     221      158832 :         for (i = 0; i < attrnum; i++) {
     222       45464 :                 if (!cb.check_size(2))
     223           0 :                         return false;
     224             : 
     225       45464 :                 if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
     226           0 :                         return false;
     227             : 
     228       45464 :                 if (u == utf8::ConstantValue) {
     229       35864 :                         if (!cb.check_size(4 + 2))
     230           0 :                                 return false;
     231             : 
     232             :                         /* check attribute length */
     233             : 
     234       35864 :                         if (cb.read_u4() != 2) {
     235           0 :                                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
     236           0 :                                 return false;
     237             :                         }
     238             : 
     239             :                         /* constant value attribute */
     240             : 
     241       35864 :                         if (pindex != field_load_NOVALUE) {
     242           0 :                                 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
     243           0 :                                 return false;
     244             :                         }
     245             : 
     246             :                         /* index of value in constantpool */
     247             : 
     248       35864 :                         pindex = cb.read_u2();
     249             : 
     250             :                         /* initialize field with value from constantpool */
     251             : 
     252       35864 :                         switch (f->type) {
     253             :                         case TYPE_INT: {
     254             :                                 int32_t *ci; 
     255             : 
     256       24174 :                                 if (!(ci = (int32_t*) class_getconstant(c, pindex, CONSTANT_Integer)))
     257           0 :                                         return false;
     258             : 
     259       24174 :                                 f->value->i = *ci;
     260             :                         }
     261       24174 :                         break;
     262             : 
     263             :                         case TYPE_LNG: {
     264             :                                 int64_t *cl; 
     265             : 
     266        7934 :                                 if (!(cl = (int64_t*) class_getconstant(c, pindex, CONSTANT_Long)))
     267           0 :                                         return false;
     268             : 
     269        7934 :                                 f->value->l = *cl;
     270             :                         }
     271        7934 :                         break;
     272             : 
     273             :                         case TYPE_FLT: {
     274             :                                 float *cf;
     275             : 
     276        1447 :                                 if (!(cf = (float*) class_getconstant(c, pindex, CONSTANT_Float)))
     277           0 :                                         return false;
     278             : 
     279        1447 :                                 f->value->f = *cf;
     280             :                         }
     281        1447 :                         break;
     282             : 
     283             :                         case TYPE_DBL: {
     284             :                                 double *cd;
     285             : 
     286        1099 :                                 if (!(cd = (double*) class_getconstant(c, pindex, CONSTANT_Double)))
     287           0 :                                         return false;
     288             : 
     289        1099 :                                 f->value->d = *cd;
     290             :                         }
     291        1099 :                         break;
     292             : 
     293             :                         case TYPE_ADR:
     294        1210 :                                 if (!(u = (utf*) class_getconstant(c, pindex, CONSTANT_String)))
     295           0 :                                         return false;
     296             : 
     297             :                                 /* Create Java-string from compressed UTF8-string. */
     298             : 
     299        1210 :                                 if (!(class_java_lang_String->flags & CLASS_LINKED))
     300        1210 :                                         linker_create_string_later(reinterpret_cast<java_object_t**>(&f->value->a), u);
     301             :                                 else
     302           0 :                                         f->value->a = JavaString::literal(u);
     303        1210 :                                 break;
     304             : 
     305             :                         default: 
     306           0 :                                 vm_abort("field_load: invalid field type %d", f->type);
     307             :                         }
     308             :                 }
     309             : #if defined(ENABLE_JAVASE)
     310        9600 :                 else if (u == utf8::Signature) {
     311             :                         /* Signature */
     312             : 
     313             :                         // TODO: change fieldinfo.signature to Utf8String
     314             :                         //       and use it directly
     315             : 
     316        9433 :                         Utf8String signature = f->signature;
     317             : 
     318        9433 :                         if (!loader_load_attribute_signature(cb, signature)) {
     319           0 :                                 return false;
     320             :                         }
     321             : 
     322        9433 :                         f->signature = signature;
     323             :                 }
     324             : 
     325             : #if defined(ENABLE_ANNOTATIONS)
     326         167 :                 else if (u == utf8::RuntimeVisibleAnnotations) {
     327             :                         /* RuntimeVisibleAnnotations */
     328           2 :                         if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
     329           0 :                                 return false;
     330             :                 }
     331         165 :                 else if (u == utf8::RuntimeInvisibleAnnotations) {
     332             :                         /* RuntimeInvisibleAnnotations */
     333           0 :                         if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
     334           0 :                                 return false;
     335             :                 }
     336             : #endif
     337             : #endif
     338             :                 else {
     339             :                         /* unknown attribute */
     340             : 
     341         165 :                         if (!loader_skip_attribute_body(cb))
     342           0 :                                 return false;
     343             :                 }
     344             :         }
     345             : 
     346             :         /* everything was ok */
     347             : 
     348      113368 :         return true;
     349             : }
     350             : 
     351             : 
     352             : /* field_get_type **************************************************************
     353             : 
     354             :    Returns the type of the field as class.
     355             : 
     356             : *******************************************************************************/
     357             : 
     358           0 : classinfo *field_get_type(fieldinfo *f)
     359             : {
     360             :         typedesc  *td;
     361           0 :         Utf8String u;
     362             :         classinfo *c;
     363             : 
     364           0 :         td = f->parseddesc;
     365             : 
     366           0 :         if (td->type == TYPE_ADR) {
     367           0 :                 assert(td->classref);
     368             : 
     369           0 :                 u = td->classref->name;
     370             : 
     371             :                 /* load the class of the field-type with the field's
     372             :                    classloader */
     373             : 
     374           0 :                 c = load_class_from_classloader(u, f->clazz->classloader);
     375             :         }
     376             :         else {
     377           0 :                 c = Primitive::get_class_by_type(td->primitivetype);
     378             :         }
     379             : 
     380           0 :         return c;
     381             : }
     382             : 
     383             : 
     384             : /* field_free ******************************************************************
     385             : 
     386             :    Frees a fields' resources.
     387             : 
     388             : *******************************************************************************/
     389             : 
     390           2 : void field_free(fieldinfo *f)
     391             : {
     392             :         /* free memory for fields which have a value */
     393             : 
     394           2 :         if (f->value)
     395             : #if defined(ENABLE_GC_BOEHM)
     396           2 :                 if (f->type != TYPE_ADR)
     397             : #endif
     398           0 :                         FREE(f->value, imm_union);
     399           2 : }
     400             : 
     401             : 
     402             : /* field_get_annotations ******************************************************
     403             : 
     404             :    Get a fields' unparsed annotations in a byte array.
     405             : 
     406             :    IN:
     407             :        f........the field of which the annotations should be returned
     408             : 
     409             :    RETURN VALUE:
     410             :        The unparsed annotations in a byte array (or NULL if there aren't any).
     411             : 
     412             : *******************************************************************************/
     413             : 
     414         879 : java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
     415             : {
     416             : #if defined(ENABLE_ANNOTATIONS)
     417             :         classinfo               *c;           /* declaring class           */
     418             :         int                      slot;        /* slot of this field        */
     419             :         java_handle_t           *field_annotations;  /* array of unparsed  */
     420             :                        /* annotations of all fields of the declaring class */
     421             : 
     422         879 :         c    = f->clazz;
     423         879 :         slot = f - c->fields;
     424             : 
     425         879 :         LLNI_classinfo_field_get(c, field_annotations, field_annotations);
     426             : 
     427         879 :         ObjectArray oa(field_annotations);
     428             : 
     429             :         /* the field_annotations array might be shorter then the field
     430             :          * count if the fields above a certain index have no annotations.
     431             :          */
     432         879 :         if (field_annotations != NULL && oa.get_length() > slot) {
     433          43 :                 return (java_handle_bytearray_t*) oa.get_element(slot);
     434             :         } else {
     435         836 :                 return NULL;
     436           0 :         }
     437             : #else
     438             :         return NULL;
     439             : #endif
     440             : }
     441             : 
     442             : 
     443             : /* field_printflags ************************************************************
     444             : 
     445             :    (debugging only)
     446             : 
     447             : *******************************************************************************/
     448             : 
     449             : #if !defined(NDEBUG)
     450           0 : void field_printflags(fieldinfo *f)
     451             : {
     452           0 :         if (f == NULL) {
     453           0 :                 printf("NULL");
     454           0 :                 return;
     455             :         }
     456             : 
     457           0 :         if (f->flags & ACC_PUBLIC)       printf(" PUBLIC");
     458           0 :         if (f->flags & ACC_PRIVATE)      printf(" PRIVATE");
     459           0 :         if (f->flags & ACC_PROTECTED)    printf(" PROTECTED");
     460           0 :         if (f->flags & ACC_STATIC)       printf(" STATIC");
     461           0 :         if (f->flags & ACC_FINAL)        printf(" FINAL");
     462           0 :         if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
     463           0 :         if (f->flags & ACC_VOLATILE)     printf(" VOLATILE");
     464           0 :         if (f->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
     465           0 :         if (f->flags & ACC_NATIVE)       printf(" NATIVE");
     466           0 :         if (f->flags & ACC_INTERFACE)    printf(" INTERFACE");
     467           0 :         if (f->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
     468             : }
     469             : #endif
     470             : 
     471             : 
     472             : /* field_print *****************************************************************
     473             : 
     474             :    (debugging only)
     475             : 
     476             : *******************************************************************************/
     477             : 
     478             : #if !defined(NDEBUG)
     479           0 : void field_print(fieldinfo *f)
     480             : {
     481           0 :         if (f == NULL) {
     482           0 :                 printf("(fieldinfo*)NULL");
     483           0 :                 return;
     484             :         }
     485             : 
     486           0 :         utf_display_printable_ascii_classname(f->clazz->name);
     487           0 :         printf(".");
     488           0 :         utf_display_printable_ascii(f->name);
     489           0 :         printf(" ");
     490           0 :         utf_display_printable_ascii(f->descriptor);  
     491             : 
     492           0 :         field_printflags(f);
     493             : 
     494           0 :         if (!(f->flags & ACC_STATIC)) {
     495           0 :                 printf(", offset: %d", f->offset);
     496             :         }
     497             : }
     498             : #endif
     499             : 
     500             : 
     501             : /* field_println ***************************************************************
     502             : 
     503             :    (debugging only)
     504             : 
     505             : *******************************************************************************/
     506             : 
     507             : #if !defined(NDEBUG)
     508           0 : void field_println(fieldinfo *f)
     509             : {
     510           0 :         field_print(f);
     511           0 :         printf("\n");
     512           0 : }
     513             : #endif
     514             : 
     515             : /* field_fieldref_print ********************************************************
     516             : 
     517             :    (debugging only)
     518             : 
     519             : *******************************************************************************/
     520             : 
     521             : #if !defined(NDEBUG)
     522           0 : void field_fieldref_print(constant_FMIref *fr)
     523             : {
     524           0 :         if (fr == NULL) {
     525           0 :                 printf("(constant_FMIref *)NULL");
     526           0 :                 return;
     527             :         }
     528             : 
     529           0 :         if (fr->is_resolved()) {
     530           0 :                 printf("<field> ");
     531           0 :                 field_print(fr->p.field);
     532             :         }
     533             :         else {
     534           0 :                 printf("<fieldref> ");
     535           0 :                 utf_display_printable_ascii_classname(fr->p.classref->name);
     536           0 :                 printf(".");
     537           0 :                 utf_display_printable_ascii(fr->name);
     538           0 :                 printf(" ");
     539           0 :                 utf_display_printable_ascii(fr->descriptor);
     540             :         }
     541             : }
     542             : #endif
     543             : 
     544             : /* field_fieldref_println ******************************************************
     545             : 
     546             :    (debugging only)
     547             : 
     548             : *******************************************************************************/
     549             : 
     550             : #if !defined(NDEBUG)
     551           0 : void field_fieldref_println(constant_FMIref *fr)
     552             : {
     553           0 :         field_fieldref_print(fr);
     554           0 :         printf("\n");
     555           0 : }
     556             : #endif
     557             : 
     558             : /*
     559             :  * These are local overrides for various environment variables in Emacs.
     560             :  * Please do not remove this and leave it at the end of the file, where
     561             :  * Emacs will automagically detect them.
     562             :  * ---------------------------------------------------------------------
     563             :  * Local variables:
     564             :  * mode: c++
     565             :  * indent-tabs-mode: t
     566             :  * c-basic-offset: 4
     567             :  * tab-width: 4
     568             :  * End:
     569             :  * vim:noexpandtab:sw=4:ts=4:
     570             :  */

Generated by: LCOV version 1.11