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
|