< prev index next >

src/hotspot/share/oops/fieldStreams.hpp

Print this page

 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  protected:
 43   const Array<u1>*    _fieldinfo_stream;
 44   FieldInfoReader     _reader;
 45   constantPoolHandle  _constants;
 46   int                 _index;
 47   int                 _limit;
 48 
 49   FieldInfo           _fi_buf;
 50   fieldDescriptor     _fd_buf;
 51 
 52   FieldInfo const * field() const {
 53     assert(!done(), "no more fields");
 54     return &_fi_buf;
 55   }
 56 
 57   inline FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit);
 58 
 59   inline FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants);
 60 
 61  private:

 99   Symbol* name() const {
100     return field()->name(_constants());
101   }
102 
103   Symbol* signature() const {
104     return field()->signature(_constants());
105   }
106 
107   Symbol* generic_signature() const {
108     if (field()->field_flags().is_generic()) {
109       return _constants->symbol_at(field()->generic_signature_index());
110     } else {
111       return nullptr;
112     }
113   }
114 
115   int offset() const {
116     return field()->offset();
117   }
118 








119   bool is_contended() const {
120     return field()->is_contended();
121   }
122 
123   int contended_group() const {
124     return field()->contended_group();
125   }
126 




127   // Convenient methods
128 
129   const FieldInfo& to_FieldInfo() const {
130     return _fi_buf;
131   }
132 
133   int num_total_fields() const {
134     return FieldInfoStream::num_total_fields(_fieldinfo_stream);
135   }
136 
137   // bridge to a heavier API:
138   fieldDescriptor& field_descriptor() const {
139     fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf);
140     field.reinitialize(field_holder(), to_FieldInfo());
141     return field;
142   }
143 };
144 
145 // Iterate over only the Java fields
146 class JavaFieldStream : public FieldStreamBase {

174   }
175 
176   // Performs either a linear search or binary search through the stream
177   // looking for a matching name/signature combo
178   bool lookup(const Symbol* name, const Symbol* signature);
179 };
180 
181 
182 // Iterate over only the internal fields
183 class InternalFieldStream : public FieldStreamBase {
184  public:
185   InternalFieldStream(InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants(), k->java_fields_count(), 0) {}
186 };
187 
188 
189 class AllFieldStream : public FieldStreamBase {
190  public:
191   AllFieldStream(const InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants()) {}
192 };
193 
194 // Iterate over fields including the ones declared in supertypes














































































195 template<typename FieldStreamType>
196 class HierarchicalFieldStream : public StackObj  {
197  private:
198   const Array<InstanceKlass*>* _interfaces;
199   InstanceKlass* _next_klass; // null indicates no more type to visit
200   FieldStreamType _current_stream;
201   int _interface_index;
202 
203   void prepare() {
204     _next_klass = next_klass_with_fields();
205     // special case: the initial klass has no fields. If any supertype has any fields, use that directly.
206     // if no such supertype exists, done() will return false already.
207     next_stream_if_done();
208   }
209 
210   InstanceKlass* next_klass_with_fields() {
211     assert(_next_klass != nullptr, "reached end of types already");
212     InstanceKlass* result = _next_klass;
213     do  {
214       if (!result->is_interface() && result->super() != nullptr) {
215         result = result->java_super();
216       } else if (_interface_index > 0) {
217         result = _interfaces->at(--_interface_index);
218       } else {
219         return nullptr; // we did not find any more supertypes with fields
220       }
221     } while (FieldStreamType(result).done());
222     return result;
223   }
224 
225   // sets _current_stream to the next if the current is done and any more is available
226   void next_stream_if_done() {
227     if (_next_klass != nullptr && _current_stream.done()) {
228       _current_stream = FieldStreamType(_next_klass);
229       assert(!_current_stream.done(), "created empty stream");
230       _next_klass = next_klass_with_fields();
231     }
232   }
233 



234  public:
235   HierarchicalFieldStream(InstanceKlass* klass) :
236     _interfaces(klass->transitive_interfaces()),
237     _next_klass(klass),
238     _current_stream(FieldStreamType(klass)),
239     _interface_index(_interfaces->length()) {
240       prepare();
241   }
242 
243   void next() {
244     _current_stream.next();
245     next_stream_if_done();
246   }
247 
248   bool done() const { return _next_klass == nullptr && _current_stream.done(); }

249 
250   // bridge functions from FieldStreamBase
251 
252   AccessFlags access_flags() const {
253     return _current_stream.access_flags();
254   }
255 
256   FieldInfo::FieldFlags field_flags() const {
257     return _current_stream.field_flags();
258   }
259 
260   Symbol* name() const {
261     return _current_stream.name();
262   }
263 
264   Symbol* signature() const {
265     return _current_stream.signature();




266   }
267 
268   Symbol* generic_signature() const {
269     return _current_stream.generic_signature();




270   }
271 
272   int offset() const {
273     return _current_stream.offset();

274   }
275 
276   bool is_contended() const {
277     return _current_stream.is_contended();


278   }
279 
280   int contended_group() const {
281     return _current_stream.contended_group();
282   }
283 
284   FieldInfo to_FieldInfo() {
285     return _current_stream.to_FieldInfo();





286   }
287 
288   fieldDescriptor& field_descriptor() const {
289     return _current_stream.field_descriptor();

290   }
291 

292 };
293 
294 #endif // SHARE_OOPS_FIELDSTREAMS_HPP

 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(const Array<u1>* fieldinfo_stream, ConstantPool* constants);
 61 
 62  private:

100   Symbol* name() const {
101     return field()->name(_constants());
102   }
103 
104   Symbol* signature() const {
105     return field()->signature(_constants());
106   }
107 
108   Symbol* generic_signature() const {
109     if (field()->field_flags().is_generic()) {
110       return _constants->symbol_at(field()->generic_signature_index());
111     } else {
112       return nullptr;
113     }
114   }
115 
116   int offset() const {
117     return field()->offset();
118   }
119 
120   bool is_null_free_inline_type() {
121     return field()->field_flags().is_null_free_inline_type();
122   }
123 
124   bool is_flat() const {
125     return field()->field_flags().is_flat();
126   }
127 
128   bool is_contended() const {
129     return field()->is_contended();
130   }
131 
132   int contended_group() const {
133     return field()->contended_group();
134   }
135 
136   int null_marker_offset() const {
137     return field()->null_marker_offset();
138   }
139 
140   // Convenient methods
141 
142   const FieldInfo& to_FieldInfo() const {
143     return _fi_buf;
144   }
145 
146   int num_total_fields() const {
147     return FieldInfoStream::num_total_fields(_fieldinfo_stream);
148   }
149 
150   // bridge to a heavier API:
151   fieldDescriptor& field_descriptor() const {
152     fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf);
153     field.reinitialize(field_holder(), to_FieldInfo());
154     return field;
155   }
156 };
157 
158 // Iterate over only the Java fields
159 class JavaFieldStream : public FieldStreamBase {

187   }
188 
189   // Performs either a linear search or binary search through the stream
190   // looking for a matching name/signature combo
191   bool lookup(const Symbol* name, const Symbol* signature);
192 };
193 
194 
195 // Iterate over only the internal fields
196 class InternalFieldStream : public FieldStreamBase {
197  public:
198   InternalFieldStream(InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants(), k->java_fields_count(), 0) {}
199 };
200 
201 
202 class AllFieldStream : public FieldStreamBase {
203  public:
204   AllFieldStream(const InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants()) {}
205 };
206 
207 /* Very generally, a base class for a stream adapter, a derived class just implements
208  * current_stream that returns a FieldStreamType, and this adapter takes care of providing
209  * the methods of FieldStreamBase.
210  *
211  * In practice, this is used to provide a stream over the fields of a class and its superclasses
212  * and interfaces. The derived class of HierarchicalFieldStreamBase decides in which order we iterate
213  * on the superclasses (and interfaces), and the template parameter FieldStreamType is the underlying
214  * stream we use to iterate over the fields each class. Methods such as done and next are still up to
215  * the derived classes, allowing them to iterate over the class hierarchy, but also skip elements that
216  * the underlying FieldStreamType would otherwise include.
217  */
218 template<typename FieldStreamType>
219 class HierarchicalFieldStreamBase : public StackObj {
220   virtual FieldStreamType& current_stream() = 0;
221   virtual const FieldStreamType& current_stream() const = 0;
222 
223 public:
224   // bridge functions from FieldStreamBase
225   int index() const {
226     return current_stream().index();
227   }
228 
229   AccessFlags access_flags() const {
230     return current_stream().access_flags();
231   }
232 
233   FieldInfo::FieldFlags field_flags() const {
234     return current_stream().field_flags();
235   }
236 
237   Symbol* name() const {
238     return current_stream().name();
239   }
240 
241   Symbol* signature() const {
242     return current_stream().signature();
243   }
244 
245   Symbol* generic_signature() const {
246     return current_stream().generic_signature();
247   }
248 
249   int offset() const {
250     return current_stream().offset();
251   }
252 
253   bool is_contended() const {
254     return current_stream().is_contended();
255   }
256 
257   int contended_group() const {
258     return current_stream().contended_group();
259   }
260 
261   FieldInfo to_FieldInfo() {
262     return current_stream().to_FieldInfo();
263   }
264 
265   fieldDescriptor& field_descriptor() const {
266     return current_stream().field_descriptor();
267   }
268 
269   bool is_flat() const {
270     return current_stream().is_flat();
271   }
272 
273   bool is_null_free_inline_type() {
274     return current_stream().is_null_free_inline_type();
275   }
276 
277   int null_marker_offset() {
278     return current_stream().null_marker_offset();
279   }
280 };
281 
282 /* Iterate over fields including the ones declared in supertypes.
283  * Derived classes are traversed before base classes, and interfaces
284  * at the end.
285  */
286 template<typename FieldStreamType>
287 class HierarchicalFieldStream final : public HierarchicalFieldStreamBase<FieldStreamType>  {
288  private:
289   const Array<InstanceKlass*>* _interfaces;
290   InstanceKlass* _next_klass; // null indicates no more type to visit
291   FieldStreamType _current_stream;
292   int _interface_index;
293 
294   void prepare() {
295     _next_klass = next_klass_with_fields();
296     // special case: the initial klass has no fields. If any supertype has any fields, use that directly.
297     // if no such supertype exists, done() will return false already.
298     next_stream_if_done();
299   }
300 
301   InstanceKlass* next_klass_with_fields() {
302     assert(_next_klass != nullptr, "reached end of types already");
303     InstanceKlass* result = _next_klass;
304     do  {
305       if (!result->is_interface() && result->super() != nullptr) {
306         result = result->java_super();
307       } else if (_interface_index > 0) {
308         result = _interfaces->at(--_interface_index);
309       } else {
310         return nullptr; // we did not find any more supertypes with fields
311       }
312     } while (FieldStreamType(result).done());
313     return result;
314   }
315 
316   // sets _current_stream to the next if the current is done and any more is available
317   void next_stream_if_done() {
318     if (_next_klass != nullptr && _current_stream.done()) {
319       _current_stream = FieldStreamType(_next_klass);
320       assert(!_current_stream.done(), "created empty stream");
321       _next_klass = next_klass_with_fields();
322     }
323   }
324 
325   FieldStreamType& current_stream() override { return _current_stream; }
326   const FieldStreamType& current_stream() const override { return _current_stream; }
327 
328  public:
329   explicit HierarchicalFieldStream(InstanceKlass* klass) :
330     _interfaces(klass->transitive_interfaces()),
331     _next_klass(klass),
332     _current_stream(FieldStreamType(klass)),
333     _interface_index(_interfaces->length()) {
334       prepare();
335   }
336 
337   void next() {
338     _current_stream.next();
339     next_stream_if_done();
340   }
341 
342   bool done() const { return _next_klass == nullptr && _current_stream.done(); }
343 };
344 
345 /* Iterates on the fields of a class and its super-class top-down (java.lang.Object first)
346  * Doesn't traverse interfaces for now, because it's not clear which order would make sense
347  * Let's decide when or if the need arises. Since we are not traversing interfaces, we
348  * wouldn't get all the static fields, and since the current use-case of this stream does not
349  * care about static fields, we restrict it to regular non-static fields.
350  */
351 class TopDownHierarchicalNonStaticFieldStreamBase final : public HierarchicalFieldStreamBase<JavaFieldStream> {
352   GrowableArray<InstanceKlass*>* _super_types;  // Self and super type, bottom up
353   int _current_stream_index;
354   JavaFieldStream _current_stream;
355 
356   void next_stream_if_needed() {
357     precond(_current_stream_index >= 0);
358     while (_current_stream.done()) {
359       _current_stream_index--;
360       if (_current_stream_index < 0) {
361         return;
362       }
363       _current_stream = JavaFieldStream(_super_types->at(_current_stream_index));
364     }
365   }
366 
367   GrowableArray<InstanceKlass*>* get_super_types(InstanceKlass* klass) {
368     auto super_types = new GrowableArray<InstanceKlass*>();
369     do {
370       super_types->push(klass);
371     } while ((klass = klass->java_super()) != nullptr);
372     return super_types;
373   }
374 
375   void raw_next() {
376     _current_stream.next();
377     next_stream_if_needed();
378   }
379 
380   void closest_non_static() {
381     while (!done() && access_flags().is_static()) {
382       raw_next();
383     }
384   }
385 
386   JavaFieldStream& current_stream() override { return _current_stream; }
387   const JavaFieldStream& current_stream() const override { return _current_stream; }

388 
389  public:
390   explicit TopDownHierarchicalNonStaticFieldStreamBase(InstanceKlass* klass) :
391     _super_types(get_super_types(klass)),
392     _current_stream_index(_super_types->length() - 1),
393     _current_stream(JavaFieldStream(_super_types->at(_current_stream_index))) {
394     next_stream_if_needed();
395     closest_non_static();
396   }
397 
398   void next() {
399     raw_next();
400     closest_non_static();
401   }
402 
403   bool done() const { return _current_stream_index < 0; }
404 };
405 
406 #endif // SHARE_OOPS_FIELDSTREAMS_HPP
< prev index next >