1 /*
  2  * Copyright (c) 2011, 2023, 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_OOPS_FIELDSTREAMS_HPP
 26 #define SHARE_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 // HierarchicalFieldStream allows to also iterate over fields of supertypes.
 41 class FieldStreamBase : public StackObj {
 42 
 43  protected:
 44   const Array<u1>*    _fieldinfo_stream;
 45   FieldInfoReader     _reader;
 46   constantPoolHandle  _constants;
 47   int                 _index;
 48   int                 _limit;
 49 
 50   FieldInfo           _fi_buf;
 51   fieldDescriptor     _fd_buf;
 52 
 53   FieldInfo const * field() const {
 54     assert(!done(), "no more fields");
 55     return &_fi_buf;
 56   }
 57 
 58   inline FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit);
 59 
 60   inline FieldStreamBase(Array<u1>* fieldinfo_stream, ConstantPool* constants);
 61 
 62   private:
 63    void initialize() {
 64     int java_fields_count = _reader.next_uint();
 65     int injected_fields_count = _reader.next_uint();
 66     assert( _limit <= java_fields_count + injected_fields_count, "Safety check");
 67     if (_limit != 0) {
 68       _reader.read_field_info(_fi_buf);
 69     }
 70    }
 71  public:
 72   inline FieldStreamBase(InstanceKlass* klass);
 73 
 74   // accessors
 75   int index() const                 { return _index; }
 76   InstanceKlass* field_holder() const { return _constants->pool_holder(); }
 77 
 78   void next() {
 79     _index += 1;
 80     if (done()) return;
 81     _reader.read_field_info(_fi_buf);
 82   }
 83   bool done() const { return _index >= _limit; }
 84 
 85   // Accessors for current field
 86   AccessFlags access_flags() const {
 87     return field()->access_flags();
 88   }
 89 
 90   FieldInfo::FieldFlags field_flags() const {
 91     return field()->field_flags();
 92   }
 93 
 94   Symbol* name() const {
 95     return field()->name(_constants());
 96   }
 97 
 98   Symbol* signature() const {
 99     return field()->signature(_constants());
100   }
101 
102   Symbol* generic_signature() const {
103     if (field()->field_flags().is_generic()) {
104       return _constants->symbol_at(field()->generic_signature_index());
105     } else {
106       return nullptr;
107     }
108   }
109 
110   int offset() const {
111     return field()->offset();
112   }
113 
114   bool is_null_free_inline_type() {
115     return field()->field_flags().is_null_free_inline_type();
116   }
117 
118   bool is_flat() {
119     return field()->field_flags().is_flat();
120   }
121 
122   bool is_contended() const {
123     return field()->is_contended();
124   }
125 
126   int contended_group() const {
127     return field()->contended_group();
128   }
129 
130   // Convenient methods
131 
132   FieldInfo to_FieldInfo() {
133     return _fi_buf;
134   }
135 
136   int num_total_fields() const {
137     return FieldInfoStream::num_total_fields(_fieldinfo_stream);
138   }
139 
140   // bridge to a heavier API:
141   fieldDescriptor& field_descriptor() const {
142     fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf);
143     field.reinitialize(field_holder(), _index);
144     return field;
145   }
146 };
147 
148 // Iterate over only the Java fields
149 class JavaFieldStream : public FieldStreamBase {
150  public:
151   JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()) {}
152 
153   u2 name_index() const {
154     assert(!field()->field_flags().is_injected(), "regular only");
155     return field()->name_index();
156   }
157 
158   u2 signature_index() const {
159     assert(!field()->field_flags().is_injected(), "regular only");
160     return field()->signature_index();
161     return -1;
162   }
163 
164   u2 generic_signature_index() const {
165     assert(!field()->field_flags().is_injected(), "regular only");
166     if (field()->field_flags().is_generic()) {
167       return field()->generic_signature_index();
168     }
169     return 0;
170   }
171 
172   u2 initval_index() const {
173     assert(!field()->field_flags().is_injected(), "regular only");
174     return field()->initializer_index();
175   }
176 };
177 
178 
179 // Iterate over only the internal fields
180 class InternalFieldStream : public FieldStreamBase {
181  public:
182   InternalFieldStream(InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants(), k->java_fields_count(), 0) {}
183 };
184 
185 
186 class AllFieldStream : public FieldStreamBase {
187  public:
188   AllFieldStream(Array<u1>* fieldinfo, ConstantPool* constants): FieldStreamBase(fieldinfo, constants) {}
189   AllFieldStream(const InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants()) {}
190 };
191 
192 // Iterate over fields including the ones declared in supertypes
193 template<typename FieldStreamType>
194 class HierarchicalFieldStream : public StackObj  {
195  private:
196   const Array<InstanceKlass*>* _interfaces;
197   InstanceKlass* _next_klass; // null indicates no more type to visit
198   FieldStreamType _current_stream;
199   int _interface_index;
200 
201   void prepare() {
202     _next_klass = next_klass_with_fields();
203     // special case: the initial klass has no fields. If any supertype has any fields, use that directly.
204     // if no such supertype exists, done() will return false already.
205     next_stream_if_done();
206   }
207 
208   InstanceKlass* next_klass_with_fields() {
209     assert(_next_klass != nullptr, "reached end of types already");
210     InstanceKlass* result = _next_klass;
211     do  {
212       if (!result->is_interface() && result->super() != nullptr) {
213         result = result->java_super();
214       } else if (_interface_index > 0) {
215         result = _interfaces->at(--_interface_index);
216       } else {
217         return nullptr; // we did not find any more supertypes with fields
218       }
219     } while (FieldStreamType(result).done());
220     return result;
221   }
222 
223   // sets _current_stream to the next if the current is done and any more is available
224   void next_stream_if_done() {
225     if (_next_klass != nullptr && _current_stream.done()) {
226       _current_stream = FieldStreamType(_next_klass);
227       assert(!_current_stream.done(), "created empty stream");
228       _next_klass = next_klass_with_fields();
229     }
230   }
231 
232  public:
233   HierarchicalFieldStream(InstanceKlass* klass) :
234     _interfaces(klass->transitive_interfaces()),
235     _next_klass(klass),
236     _current_stream(FieldStreamType(klass)),
237     _interface_index(_interfaces->length()) {
238       prepare();
239   }
240 
241   void next() {
242     _current_stream.next();
243     next_stream_if_done();
244   }
245 
246   bool done() const { return _next_klass == nullptr && _current_stream.done(); }
247 
248   // bridge functions from FieldStreamBase
249 
250   AccessFlags access_flags() const {
251     return _current_stream.access_flags();
252   }
253 
254   FieldInfo::FieldFlags field_flags() const {
255     return _current_stream.field_flags();
256   }
257 
258   Symbol* name() const {
259     return _current_stream.name();
260   }
261 
262   Symbol* signature() const {
263     return _current_stream.signature();
264   }
265 
266   Symbol* generic_signature() const {
267     return _current_stream.generic_signature();
268   }
269 
270   int offset() const {
271     return _current_stream.offset();
272   }
273 
274   bool is_contended() const {
275     return _current_stream.is_contended();
276   }
277 
278   int contended_group() const {
279     return _current_stream.contended_group();
280   }
281 
282   FieldInfo to_FieldInfo() {
283     return _current_stream.to_FieldInfo();
284   }
285 
286   fieldDescriptor& field_descriptor() const {
287     return _current_stream.field_descriptor();
288   }
289 
290 };
291 
292 #endif // SHARE_OOPS_FIELDSTREAMS_HPP