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

 93   Symbol* name() const {
 94     return field()->name(_constants());
 95   }
 96 
 97   Symbol* signature() const {
 98     return field()->signature(_constants());
 99   }
100 
101   Symbol* generic_signature() const {
102     if (field()->field_flags().is_generic()) {
103       return _constants->symbol_at(field()->generic_signature_index());
104     } else {
105       return nullptr;
106     }
107   }
108 
109   int offset() const {
110     return field()->offset();
111   }
112 








113   bool is_contended() const {
114     return field()->is_contended();
115   }
116 
117   int contended_group() const {
118     return field()->contended_group();
119   }
120 




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

163   u2 initval_index() const {
164     assert(!field()->field_flags().is_injected(), "regular only");
165     return field()->initializer_index();
166   }
167 };
168 
169 
170 // Iterate over only the internal fields
171 class InternalFieldStream : public FieldStreamBase {
172  public:
173   InternalFieldStream(InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants(), k->java_fields_count(), 0) {}
174 };
175 
176 
177 class AllFieldStream : public FieldStreamBase {
178  public:
179   AllFieldStream(Array<u1>* fieldinfo, ConstantPool* constants): FieldStreamBase(fieldinfo, constants) {}
180   AllFieldStream(const InstanceKlass* k):      FieldStreamBase(k->fieldinfo_stream(), k->constants()) {}
181 };
182 
183 // Iterate over fields including the ones declared in supertypes














































































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



223  public:
224   HierarchicalFieldStream(InstanceKlass* klass) :
225     _interfaces(klass->transitive_interfaces()),
226     _next_klass(klass),
227     _current_stream(FieldStreamType(klass)),
228     _interface_index(_interfaces->length()) {
229       prepare();
230   }
231 
232   void next() {
233     _current_stream.next();
234     next_stream_if_done();
235   }
236 
237   bool done() const { return _next_klass == nullptr && _current_stream.done(); }

238 
239   // bridge functions from FieldStreamBase
240 
241   AccessFlags access_flags() const {
242     return _current_stream.access_flags();
243   }
244 
245   FieldInfo::FieldFlags field_flags() const {
246     return _current_stream.field_flags();
247   }
248 
249   Symbol* name() const {
250     return _current_stream.name();
251   }
252 
253   Symbol* signature() const {
254     return _current_stream.signature();




255   }
256 
257   Symbol* generic_signature() const {
258     return _current_stream.generic_signature();




259   }
260 
261   int offset() const {
262     return _current_stream.offset();

263   }
264 
265   bool is_contended() const {
266     return _current_stream.is_contended();


267   }
268 
269   int contended_group() const {
270     return _current_stream.contended_group();
271   }
272 
273   FieldInfo to_FieldInfo() {
274     return _current_stream.to_FieldInfo();





275   }
276 
277   fieldDescriptor& field_descriptor() const {
278     return _current_stream.field_descriptor();

279   }
280 

281 };
282 
283 #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(Array<u1>* fieldinfo_stream, ConstantPool* constants);
 61 
 62   private:

 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() const {
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   int null_marker_offset() const {
131     return field()->null_marker_offset();
132   }
133 
134   // Convenient methods
135 
136   const FieldInfo& to_FieldInfo() const {
137     return _fi_buf;
138   }
139 
140   int num_total_fields() const {
141     return FieldInfoStream::num_total_fields(_fieldinfo_stream);
142   }
143 
144   // bridge to a heavier API:
145   fieldDescriptor& field_descriptor() const {
146     fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf);
147     field.reinitialize(field_holder(), to_FieldInfo());
148     return field;
149   }
150 };
151 
152 // Iterate over only the Java fields
153 class JavaFieldStream : public FieldStreamBase {

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

377 
378  public:
379   explicit TopDownHierarchicalNonStaticFieldStreamBase(InstanceKlass* klass) :
380     _super_types(get_super_types(klass)),
381     _current_stream_index(_super_types->length() - 1),
382     _current_stream(JavaFieldStream(_super_types->at(_current_stream_index))) {
383     next_stream_if_needed();
384     closest_non_static();
385   }
386 
387   void next() {
388     raw_next();
389     closest_non_static();
390   }
391 
392   bool done() const { return _current_stream_index < 0; }
393 };
394 
395 #endif // SHARE_OOPS_FIELDSTREAMS_HPP
< prev index next >