1 /* 2 * Copyright (c) 2011, 2025, 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 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: 62 void initialize() { 63 int java_fields_count; 64 int injected_fields_count; 65 _reader.read_field_counts(&java_fields_count, &injected_fields_count); 66 if (_limit < _index) { 67 _limit = java_fields_count + injected_fields_count; 68 } else { 69 assert( _limit <= java_fields_count + injected_fields_count, "Safety check"); 70 } 71 if (_limit != 0) { 72 _reader.read_field_info(_fi_buf); 73 } 74 } 75 76 public: 77 inline FieldStreamBase(InstanceKlass* klass); 78 79 // accessors 80 int index() const { return _index; } 81 InstanceKlass* field_holder() const { return _constants->pool_holder(); } 82 83 void next() { 84 _index += 1; 85 if (done()) return; 86 _reader.read_field_info(_fi_buf); 87 } 88 bool done() const { return _index >= _limit; } 89 90 // Accessors for current field 91 AccessFlags access_flags() const { 92 return field()->access_flags(); 93 } 94 95 FieldInfo::FieldFlags field_flags() const { 96 return field()->field_flags(); 97 } 98 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 { 147 Array<u1>* _search_table; 148 149 public: 150 JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()), 151 _search_table(k->fieldinfo_search_table()) {} 152 153 u2 name_index() const { 154 assert(!field()->field_flags().is_injected(), "regular only"); 155 return field()->name_index(); 156 } 157 158 u2 signature_index() const { 159 assert(!field()->field_flags().is_injected(), "regular only"); 160 return field()->signature_index(); 161 } 162 163 u2 generic_signature_index() const { 164 assert(!field()->field_flags().is_injected(), "regular only"); 165 if (field()->field_flags().is_generic()) { 166 return field()->generic_signature_index(); 167 } 168 return 0; 169 } 170 171 u2 initval_index() const { 172 assert(!field()->field_flags().is_injected(), "regular only"); 173 return field()->initializer_index(); 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