aoqi@0: /* aoqi@0: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_RUNTIME_REFLECTIONUTILS_HPP aoqi@0: #define SHARE_VM_RUNTIME_REFLECTIONUTILS_HPP aoqi@0: aoqi@0: #include "memory/allocation.hpp" aoqi@0: #include "oops/instanceKlass.hpp" aoqi@0: #include "oops/objArrayOop.hpp" aoqi@0: #include "oops/oopsHierarchy.hpp" aoqi@0: #include "runtime/handles.inline.hpp" aoqi@0: #include "runtime/reflection.hpp" aoqi@0: #include "utilities/accessFlags.hpp" aoqi@0: #include "utilities/globalDefinitions.hpp" aoqi@0: aoqi@0: // A KlassStream is an abstract stream for streaming over self, superclasses aoqi@0: // and (super)interfaces. Streaming is done in reverse order (subclasses first, aoqi@0: // interfaces last). aoqi@0: // aoqi@0: // for (KlassStream st(k, false, false, false); !st.eos(); st.next()) { aoqi@0: // Klass* k = st.klass(); aoqi@0: // ... aoqi@0: // } aoqi@0: aoqi@0: class KlassStream VALUE_OBJ_CLASS_SPEC { aoqi@0: protected: aoqi@0: instanceKlassHandle _klass; // current klass/interface iterated over aoqi@0: instanceKlassHandle _base_klass; // initial klass/interface to iterate over aoqi@0: Array* _interfaces; // transitive interfaces for initial class aoqi@0: int _interface_index; // current interface being processed aoqi@0: bool _local_only; // process initial class/interface only aoqi@0: bool _classes_only; // process classes only (no interfaces) aoqi@0: bool _walk_defaults; // process default methods aoqi@0: bool _base_class_search_defaults; // time to process default methods aoqi@0: bool _defaults_checked; // already checked for default methods aoqi@0: int _index; aoqi@0: aoqi@0: virtual int length() = 0; aoqi@0: aoqi@0: public: aoqi@0: // constructor aoqi@0: KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only, bool walk_defaults); aoqi@0: aoqi@0: // testing aoqi@0: bool eos(); aoqi@0: aoqi@0: // iterating aoqi@0: virtual void next() = 0; aoqi@0: aoqi@0: // accessors aoqi@0: instanceKlassHandle klass() const { return _klass; } aoqi@0: int index() const { return _index; } aoqi@0: bool base_class_search_defaults() const { return _base_class_search_defaults; } aoqi@0: void base_class_search_defaults(bool b) { _base_class_search_defaults = b; } aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: // A MethodStream streams over all methods in a class, superclasses and (super)interfaces. aoqi@0: // Streaming is done in reverse order (subclasses first, methods in reverse order) aoqi@0: // Usage: aoqi@0: // aoqi@0: // for (MethodStream st(k, false, false); !st.eos(); st.next()) { aoqi@0: // Method* m = st.method(); aoqi@0: // ... aoqi@0: // } aoqi@0: aoqi@0: class MethodStream : public KlassStream { aoqi@0: private: aoqi@0: int length() { return methods()->length(); } aoqi@0: Array* methods() { aoqi@0: if (base_class_search_defaults()) { aoqi@0: base_class_search_defaults(false); aoqi@0: return _klass->default_methods(); aoqi@0: } else { aoqi@0: return _klass->methods(); aoqi@0: } aoqi@0: } aoqi@0: public: aoqi@0: MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only) aoqi@0: : KlassStream(klass, local_only, classes_only, true) { aoqi@0: _index = length(); aoqi@0: next(); aoqi@0: } aoqi@0: aoqi@0: void next() { _index--; } aoqi@0: Method* method() { return methods()->at(index()); } aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: // A FieldStream streams over all fields in a class, superclasses and (super)interfaces. aoqi@0: // Streaming is done in reverse order (subclasses first, fields in reverse order) aoqi@0: // Usage: aoqi@0: // aoqi@0: // for (FieldStream st(k, false, false); !st.eos(); st.next()) { aoqi@0: // Symbol* field_name = st.name(); aoqi@0: // ... aoqi@0: // } aoqi@0: aoqi@0: aoqi@0: class FieldStream : public KlassStream { aoqi@0: private: aoqi@0: int length() { return _klass->java_fields_count(); } aoqi@0: aoqi@0: fieldDescriptor _fd_buf; aoqi@0: aoqi@0: public: aoqi@0: FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) aoqi@0: : KlassStream(klass, local_only, classes_only, false) { aoqi@0: _index = length(); aoqi@0: next(); aoqi@0: } aoqi@0: aoqi@0: void next() { _index -= 1; } aoqi@0: aoqi@0: // Accessors for current field aoqi@0: AccessFlags access_flags() const { aoqi@0: AccessFlags flags; aoqi@0: flags.set_flags(_klass->field_access_flags(_index)); aoqi@0: return flags; aoqi@0: } aoqi@0: Symbol* name() const { aoqi@0: return _klass->field_name(_index); aoqi@0: } aoqi@0: Symbol* signature() const { aoqi@0: return _klass->field_signature(_index); aoqi@0: } aoqi@0: // missing: initval() aoqi@0: int offset() const { aoqi@0: return _klass->field_offset( index() ); aoqi@0: } aoqi@0: // bridge to a heavier API: aoqi@0: fieldDescriptor& field_descriptor() const { aoqi@0: fieldDescriptor& field = const_cast(_fd_buf); aoqi@0: field.reinitialize(_klass(), _index); aoqi@0: return field; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: class FilteredField : public CHeapObj { aoqi@0: private: aoqi@0: Klass* _klass; aoqi@0: int _field_offset; aoqi@0: aoqi@0: public: aoqi@0: FilteredField(Klass* klass, int field_offset) { aoqi@0: _klass = klass; aoqi@0: _field_offset = field_offset; aoqi@0: } aoqi@0: Klass* klass() { return _klass; } aoqi@0: int field_offset() { return _field_offset; } aoqi@0: }; aoqi@0: aoqi@0: class FilteredFieldsMap : AllStatic { aoqi@0: private: aoqi@0: static GrowableArray *_filtered_fields; aoqi@0: public: aoqi@0: static void initialize(); aoqi@0: static bool is_filtered_field(Klass* klass, int field_offset) { aoqi@0: for (int i=0; i < _filtered_fields->length(); i++) { aoqi@0: if (klass == _filtered_fields->at(i)->klass() && aoqi@0: field_offset == _filtered_fields->at(i)->field_offset()) { aoqi@0: return true; aoqi@0: } aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: static int filtered_fields_count(Klass* klass, bool local_only) { aoqi@0: int nflds = 0; aoqi@0: for (int i=0; i < _filtered_fields->length(); i++) { aoqi@0: if (local_only && klass == _filtered_fields->at(i)->klass()) { aoqi@0: nflds++; aoqi@0: } else if (klass->is_subtype_of(_filtered_fields->at(i)->klass())) { aoqi@0: nflds++; aoqi@0: } aoqi@0: } aoqi@0: return nflds; aoqi@0: } aoqi@0: // Enhance Class Redefinition Support aoqi@0: static void classes_do(KlassClosure* f) { aoqi@0: for (int i = 0; i < _filtered_fields->length(); i++) { aoqi@0: f->do_klass(_filtered_fields->at(i)->klass()); aoqi@0: } aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: // A FilteredFieldStream streams over all fields in a class, superclasses and aoqi@0: // (super)interfaces. Streaming is done in reverse order (subclasses first, aoqi@0: // fields in reverse order) aoqi@0: // aoqi@0: // Usage: aoqi@0: // aoqi@0: // for (FilteredFieldStream st(k, false, false); !st.eos(); st.next()) { aoqi@0: // Symbol* field_name = st.name(); aoqi@0: // ... aoqi@0: // } aoqi@0: aoqi@0: class FilteredFieldStream : public FieldStream { aoqi@0: private: aoqi@0: int _filtered_fields_count; aoqi@0: bool has_filtered_field() { return (_filtered_fields_count > 0); } aoqi@0: aoqi@0: public: aoqi@0: FilteredFieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) aoqi@0: : FieldStream(klass, local_only, classes_only) { aoqi@0: _filtered_fields_count = FilteredFieldsMap::filtered_fields_count((Klass*)klass(), local_only); aoqi@0: } aoqi@0: int field_count(); aoqi@0: void next() { aoqi@0: _index -= 1; aoqi@0: if (has_filtered_field()) { aoqi@0: while (_index >=0 && FilteredFieldsMap::is_filtered_field((Klass*)_klass(), offset())) { aoqi@0: _index -= 1; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_RUNTIME_REFLECTIONUTILS_HPP