| 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 |
| 73 | InstanceKlass* klass() const { return _klass; } |
| 74 | int index() const { return _index; } |
| 75 | bool base_class_search_defaults() const { return _base_class_search_defaults; } |
| 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: |
| 91 | int length() { return methods()->length(); } |
| 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: |
| 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 | |
| 107 | void next() { _index--; } |
| 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: |
| 124 | int length() { return _klass->java_fields_count(); } |
| 125 | |
| 126 | fieldDescriptor _fd_buf; |
| 127 | |
| 128 | public: |
| 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 | |
| 135 | void next() { _index -= 1; } |
| 136 | |
| 137 | // Accessors for current field |
| 138 | AccessFlags access_flags() const { |
| 139 | AccessFlags flags; |
| 140 | flags.set_flags(_klass->field_access_flags(_index)); |
| 141 | return flags; |
| 142 | } |
| 143 | Symbol* name() const { |
| 144 | return _klass->field_name(_index); |
| 145 | } |
| 146 | Symbol* signature() const { |
| 147 | return _klass->field_signature(_index); |
| 148 | } |
| 149 | // missing: initval() |
| 150 | int offset() const { |
| 151 | return _klass->field_offset( index() ); |
| 152 | } |
| 153 | // bridge to a heavier API: |
| 154 | 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: |
| 167 | FilteredField(Klass* klass, int field_offset) { |
| 168 | _klass = klass; |
| 169 | _field_offset = field_offset; |
| 170 | } |
| 171 | Klass* klass() { return _klass; } |
| 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(); |
| 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 | } |
| 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; |
| 217 | bool has_filtered_field() { return (_filtered_fields_count > 0); } |
| 218 | |
| 219 | public: |
| 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(); |
| 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 | |