src/hotspot/share/oops/fieldStreams.hpp
changeset 47216 71c04702a3d5
parent 46329 53ccc37bda19
child 53244 9807daeb47c4
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #ifndef SHARE_VM_OOPS_FIELDSTREAMS_HPP
       
    26 #define SHARE_VM_OOPS_FIELDSTREAMS_HPP
       
    27 
       
    28 #include "oops/instanceKlass.hpp"
       
    29 #include "oops/fieldInfo.hpp"
       
    30 #include "runtime/fieldDescriptor.hpp"
       
    31 
       
    32 // The is the base class for iteration over the fields array
       
    33 // describing the declared fields in the class.  Several subclasses
       
    34 // are provided depending on the kind of iteration required.  The
       
    35 // JavaFieldStream is for iterating over regular Java fields and it
       
    36 // generally the preferred iterator.  InternalFieldStream only
       
    37 // iterates over fields that have been injected by the JVM.
       
    38 // AllFieldStream exposes all fields and should only be used in rare
       
    39 // cases.
       
    40 class FieldStreamBase : public StackObj {
       
    41  protected:
       
    42   Array<u2>*          _fields;
       
    43   constantPoolHandle  _constants;
       
    44   int                 _index;
       
    45   int                 _limit;
       
    46   int                 _generic_signature_slot;
       
    47   fieldDescriptor     _fd_buf;
       
    48 
       
    49   FieldInfo* field() const { return FieldInfo::from_field_array(_fields, _index); }
       
    50   InstanceKlass* field_holder() const { return _constants->pool_holder(); }
       
    51 
       
    52   int init_generic_signature_start_slot() {
       
    53     int length = _fields->length();
       
    54     int num_fields = _index;
       
    55     int skipped_generic_signature_slots = 0;
       
    56     FieldInfo* fi;
       
    57     AccessFlags flags;
       
    58     /* Scan from 0 to the current _index. Count the number of generic
       
    59        signature slots for field[0] to field[_index - 1]. */
       
    60     for (int i = 0; i < _index; i++) {
       
    61       fi = FieldInfo::from_field_array(_fields, i);
       
    62       flags.set_flags(fi->access_flags());
       
    63       if (flags.field_has_generic_signature()) {
       
    64         length --;
       
    65         skipped_generic_signature_slots ++;
       
    66       }
       
    67     }
       
    68     /* Scan from the current _index. */
       
    69     for (int i = _index; i*FieldInfo::field_slots < length; i++) {
       
    70       fi = FieldInfo::from_field_array(_fields, i);
       
    71       flags.set_flags(fi->access_flags());
       
    72       if (flags.field_has_generic_signature()) {
       
    73         length --;
       
    74       }
       
    75       num_fields ++;
       
    76     }
       
    77     _generic_signature_slot = length + skipped_generic_signature_slots;
       
    78     assert(_generic_signature_slot <= _fields->length(), "");
       
    79     return num_fields;
       
    80   }
       
    81 
       
    82   FieldStreamBase(Array<u2>* fields, const constantPoolHandle& constants, int start, int limit) {
       
    83     _fields = fields;
       
    84     _constants = constants;
       
    85     _index = start;
       
    86     int num_fields = init_generic_signature_start_slot();
       
    87     if (limit < start) {
       
    88       _limit = num_fields;
       
    89     } else {
       
    90       _limit = limit;
       
    91     }
       
    92   }
       
    93 
       
    94   FieldStreamBase(Array<u2>* fields, const constantPoolHandle& constants) {
       
    95     _fields = fields;
       
    96     _constants = constants;
       
    97     _index = 0;
       
    98     _limit = init_generic_signature_start_slot();
       
    99   }
       
   100 
       
   101  public:
       
   102   FieldStreamBase(InstanceKlass* klass) {
       
   103     _fields = klass->fields();
       
   104     _constants = klass->constants();
       
   105     _index = 0;
       
   106     _limit = klass->java_fields_count();
       
   107     init_generic_signature_start_slot();
       
   108     assert(klass == field_holder(), "");
       
   109   }
       
   110 
       
   111   // accessors
       
   112   int index() const                 { return _index; }
       
   113 
       
   114   void next() {
       
   115     if (access_flags().field_has_generic_signature()) {
       
   116       _generic_signature_slot ++;
       
   117       assert(_generic_signature_slot <= _fields->length(), "");
       
   118     }
       
   119     _index += 1;
       
   120   }
       
   121   bool done() const { return _index >= _limit; }
       
   122 
       
   123   // Accessors for current field
       
   124   AccessFlags access_flags() const {
       
   125     AccessFlags flags;
       
   126     flags.set_flags(field()->access_flags());
       
   127     return flags;
       
   128   }
       
   129 
       
   130   void set_access_flags(u2 flags) const {
       
   131     field()->set_access_flags(flags);
       
   132   }
       
   133 
       
   134   void set_access_flags(AccessFlags flags) const {
       
   135     set_access_flags(flags.as_short());
       
   136   }
       
   137 
       
   138   Symbol* name() const {
       
   139     return field()->name(_constants);
       
   140   }
       
   141 
       
   142   Symbol* signature() const {
       
   143     return field()->signature(_constants);
       
   144   }
       
   145 
       
   146   Symbol* generic_signature() const {
       
   147     if (access_flags().field_has_generic_signature()) {
       
   148       assert(_generic_signature_slot < _fields->length(), "out of bounds");
       
   149       int index = _fields->at(_generic_signature_slot);
       
   150       return _constants->symbol_at(index);
       
   151     } else {
       
   152       return NULL;
       
   153     }
       
   154   }
       
   155 
       
   156   int offset() const {
       
   157     return field()->offset();
       
   158   }
       
   159 
       
   160   int allocation_type() const {
       
   161     return field()->allocation_type();
       
   162   }
       
   163 
       
   164   void set_offset(int offset) {
       
   165     field()->set_offset(offset);
       
   166   }
       
   167 
       
   168   bool is_offset_set() const {
       
   169     return field()->is_offset_set();
       
   170   }
       
   171 
       
   172   bool is_contended() const {
       
   173     return field()->is_contended();
       
   174   }
       
   175 
       
   176   int contended_group() const {
       
   177     return field()->contended_group();
       
   178   }
       
   179 
       
   180   // bridge to a heavier API:
       
   181   fieldDescriptor& field_descriptor() const {
       
   182     fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf);
       
   183     field.reinitialize(field_holder(), _index);
       
   184     return field;
       
   185   }
       
   186 };
       
   187 
       
   188 // Iterate over only the internal fields
       
   189 class JavaFieldStream : public FieldStreamBase {
       
   190  public:
       
   191   JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {}
       
   192 
       
   193   int name_index() const {
       
   194     assert(!field()->is_internal(), "regular only");
       
   195     return field()->name_index();
       
   196   }
       
   197   void set_name_index(int index) {
       
   198     assert(!field()->is_internal(), "regular only");
       
   199     field()->set_name_index(index);
       
   200   }
       
   201   int signature_index() const {
       
   202     assert(!field()->is_internal(), "regular only");
       
   203     return field()->signature_index();
       
   204   }
       
   205   void set_signature_index(int index) {
       
   206     assert(!field()->is_internal(), "regular only");
       
   207     field()->set_signature_index(index);
       
   208   }
       
   209   int generic_signature_index() const {
       
   210     assert(!field()->is_internal(), "regular only");
       
   211     if (access_flags().field_has_generic_signature()) {
       
   212       assert(_generic_signature_slot < _fields->length(), "out of bounds");
       
   213       return _fields->at(_generic_signature_slot);
       
   214     } else {
       
   215       return 0;
       
   216     }
       
   217   }
       
   218   void set_generic_signature_index(int index) {
       
   219     assert(!field()->is_internal(), "regular only");
       
   220     if (access_flags().field_has_generic_signature()) {
       
   221       assert(_generic_signature_slot < _fields->length(), "out of bounds");
       
   222       _fields->at_put(_generic_signature_slot, index);
       
   223     }
       
   224   }
       
   225   int initval_index() const {
       
   226     assert(!field()->is_internal(), "regular only");
       
   227     return field()->initval_index();
       
   228   }
       
   229   void set_initval_index(int index) {
       
   230     assert(!field()->is_internal(), "regular only");
       
   231     return field()->set_initval_index(index);
       
   232   }
       
   233 };
       
   234 
       
   235 
       
   236 // Iterate over only the internal fields
       
   237 class InternalFieldStream : public FieldStreamBase {
       
   238  public:
       
   239   InternalFieldStream(InstanceKlass* k):      FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), 0) {}
       
   240 };
       
   241 
       
   242 
       
   243 class AllFieldStream : public FieldStreamBase {
       
   244  public:
       
   245   AllFieldStream(Array<u2>* fields, const constantPoolHandle& constants): FieldStreamBase(fields, constants) {}
       
   246   AllFieldStream(InstanceKlass* k):      FieldStreamBase(k->fields(), k->constants()) {}
       
   247 };
       
   248 
       
   249 #endif // SHARE_VM_OOPS_FIELDSTREAMS_HPP