1 /* 2 * Copyright (c) 1999, 2019, 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_RUNTIME_REFLECTIONUTILS_HPP 26 #define SHARE_RUNTIME_REFLECTIONUTILS_HPP 27 28 #include "memory/allocation.hpp" 29 #include "oops/instanceKlass.hpp" 30 #include "oops/objArrayOop.hpp" 31 #include "oops/oopsHierarchy.hpp" 32 #include "runtime/handles.hpp" 33 #include "runtime/reflection.hpp" 34 #include "utilities/accessFlags.hpp" 35 #include "utilities/globalDefinitions.hpp" 36 #include "utilities/growableArray.hpp" 37 38 // A KlassStream is an abstract stream for streaming over self, superclasses 39 // and (super)interfaces. Streaming is done in reverse order (subclasses first, 40 // interfaces last). 41 // 42 // for (KlassStream st(k, false, false, false); !st.eos(); st.next()) { 43 // Klass* k = st.klass(); 44 // ... 45 // } 46 47 class KlassStream { 48 protected: 49 InstanceKlass* _klass; // current klass/interface iterated over 50 InstanceKlass* _base_klass; // initial klass/interface to iterate over 51 Array<InstanceKlass*>*_interfaces; // transitive interfaces for initial class 52 int _interface_index; // current interface being processed 53 bool _local_only; // process initial class/interface only 54 bool _classes_only; // process classes only (no interfaces) 55 bool _walk_defaults; // process default methods 56 bool _base_class_search_defaults; // time to process default methods 57 bool _defaults_checked; // already checked for default methods 58 int _index; 59 60 virtual int length() = 0; 61 62 public: 63 // constructor 64 KlassStream(InstanceKlass* klass, bool local_only, bool classes_only, bool walk_defaults); 65 66 // testing 67 bool eos(); 68 69 // iterating 70 virtual void next() = 0; 71 72 // accessors klass() const73 InstanceKlass* klass() const { return _klass; } index() const74 int index() const { return _index; } base_class_search_defaults() const75 bool base_class_search_defaults() const { return _base_class_search_defaults; } base_class_search_defaults(bool b)76 void base_class_search_defaults(bool b) { _base_class_search_defaults = b; } 77 }; 78 79 80 // A MethodStream streams over all methods in a class, superclasses and (super)interfaces. 81 // Streaming is done in reverse order (subclasses first, methods in reverse order) 82 // Usage: 83 // 84 // for (MethodStream st(k, false, false); !st.eos(); st.next()) { 85 // Method* m = st.method(); 86 // ... 87 // } 88 89 class MethodStream : public KlassStream { 90 private: length()91 int length() { return methods()->length(); } methods()92 Array<Method*>* methods() { 93 if (base_class_search_defaults()) { 94 base_class_search_defaults(false); 95 return _klass->default_methods(); 96 } else { 97 return _klass->methods(); 98 } 99 } 100 public: MethodStream(InstanceKlass * klass,bool local_only,bool classes_only)101 MethodStream(InstanceKlass* klass, bool local_only, bool classes_only) 102 : KlassStream(klass, local_only, classes_only, true) { 103 _index = length(); 104 next(); 105 } 106 next()107 void next() { _index--; } method()108 Method* method() { return methods()->at(index()); } 109 }; 110 111 112 // A FieldStream streams over all fields in a class, superclasses and (super)interfaces. 113 // Streaming is done in reverse order (subclasses first, fields in reverse order) 114 // Usage: 115 // 116 // for (FieldStream st(k, false, false); !st.eos(); st.next()) { 117 // Symbol* field_name = st.name(); 118 // ... 119 // } 120 121 122 class FieldStream : public KlassStream { 123 private: length()124 int length() { return _klass->java_fields_count(); } 125 126 fieldDescriptor _fd_buf; 127 128 public: FieldStream(InstanceKlass * klass,bool local_only,bool classes_only)129 FieldStream(InstanceKlass* klass, bool local_only, bool classes_only) 130 : KlassStream(klass, local_only, classes_only, false) { 131 _index = length(); 132 next(); 133 } 134 next()135 void next() { _index -= 1; } 136 137 // Accessors for current field access_flags() const138 AccessFlags access_flags() const { 139 AccessFlags flags; 140 flags.set_flags(_klass->field_access_flags(_index)); 141 return flags; 142 } name() const143 Symbol* name() const { 144 return _klass->field_name(_index); 145 } signature() const146 Symbol* signature() const { 147 return _klass->field_signature(_index); 148 } 149 // missing: initval() offset() const150 int offset() const { 151 return _klass->field_offset( index() ); 152 } 153 // bridge to a heavier API: field_descriptor() const154 fieldDescriptor& field_descriptor() const { 155 fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf); 156 field.reinitialize(_klass, _index); 157 return field; 158 } 159 }; 160 161 class FilteredField : public CHeapObj<mtInternal> { 162 private: 163 Klass* _klass; 164 int _field_offset; 165 166 public: FilteredField(Klass * klass,int field_offset)167 FilteredField(Klass* klass, int field_offset) { 168 _klass = klass; 169 _field_offset = field_offset; 170 } klass()171 Klass* klass() { return _klass; } field_offset()172 int field_offset() { return _field_offset; } 173 }; 174 175 class FilteredFieldsMap : AllStatic { 176 private: 177 static GrowableArray<FilteredField *> *_filtered_fields; 178 public: 179 static void initialize(); is_filtered_field(Klass * klass,int field_offset)180 static bool is_filtered_field(Klass* klass, int field_offset) { 181 for (int i=0; i < _filtered_fields->length(); i++) { 182 if (klass == _filtered_fields->at(i)->klass() && 183 field_offset == _filtered_fields->at(i)->field_offset()) { 184 return true; 185 } 186 } 187 return false; 188 } filtered_fields_count(Klass * klass,bool local_only)189 static int filtered_fields_count(Klass* klass, bool local_only) { 190 int nflds = 0; 191 for (int i=0; i < _filtered_fields->length(); i++) { 192 if (local_only && klass == _filtered_fields->at(i)->klass()) { 193 nflds++; 194 } else if (klass->is_subtype_of(_filtered_fields->at(i)->klass())) { 195 nflds++; 196 } 197 } 198 return nflds; 199 } 200 }; 201 202 203 // A FilteredFieldStream streams over all fields in a class, superclasses and 204 // (super)interfaces. Streaming is done in reverse order (subclasses first, 205 // fields in reverse order) 206 // 207 // Usage: 208 // 209 // for (FilteredFieldStream st(k, false, false); !st.eos(); st.next()) { 210 // Symbol* field_name = st.name(); 211 // ... 212 // } 213 214 class FilteredFieldStream : public FieldStream { 215 private: 216 int _filtered_fields_count; has_filtered_field()217 bool has_filtered_field() { return (_filtered_fields_count > 0); } 218 219 public: FilteredFieldStream(InstanceKlass * klass,bool local_only,bool classes_only)220 FilteredFieldStream(InstanceKlass* klass, bool local_only, bool classes_only) 221 : FieldStream(klass, local_only, classes_only) { 222 _filtered_fields_count = FilteredFieldsMap::filtered_fields_count(klass, local_only); 223 } 224 int field_count(); next()225 void next() { 226 _index -= 1; 227 if (has_filtered_field()) { 228 while (_index >=0 && FilteredFieldsMap::is_filtered_field((Klass*)_klass, offset())) { 229 _index -= 1; 230 } 231 } 232 } 233 }; 234 235 #endif // SHARE_RUNTIME_REFLECTIONUTILS_HPP 236