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
|