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() 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 { 154 public: 155 JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()) {} 156 157 u2 name_index() const { 158 assert(!field()->field_flags().is_injected(), "regular only"); 159 return field()->name_index(); 160 } 161 162 u2 signature_index() const { 163 assert(!field()->field_flags().is_injected(), "regular only"); 164 return field()->signature_index(); 165 return -1; 166 } 167 168 u2 generic_signature_index() const { 169 assert(!field()->field_flags().is_injected(), "regular only"); 170 if (field()->field_flags().is_generic()) { 171 return field()->generic_signature_index(); 172 } 173 return 0; 174 } 175 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