duke@435: /* duke@435: * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: // A KlassStream is an abstract stream for streaming over self, superclasses duke@435: // and (super)interfaces. Streaming is done in reverse order (subclasses first, duke@435: // interfaces last). duke@435: // duke@435: // for (KlassStream st(k, false, false); !st.eos(); st.next()) { duke@435: // klassOop k = st.klass(); duke@435: // ... duke@435: // } duke@435: duke@435: class KlassStream VALUE_OBJ_CLASS_SPEC { duke@435: protected: duke@435: instanceKlassHandle _klass; // current klass/interface iterated over duke@435: objArrayHandle _interfaces; // transitive interfaces for initial class duke@435: int _interface_index; // current interface being processed duke@435: bool _local_only; // process initial class/interface only duke@435: bool _classes_only; // process classes only (no interfaces) duke@435: int _index; duke@435: duke@435: virtual int length() const = 0; duke@435: duke@435: public: duke@435: // constructor duke@435: KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only); duke@435: duke@435: // testing duke@435: bool eos(); duke@435: duke@435: // iterating duke@435: virtual void next() = 0; duke@435: duke@435: // accessors duke@435: instanceKlassHandle klass() const { return _klass; } duke@435: int index() const { return _index; } duke@435: }; duke@435: duke@435: duke@435: // A MethodStream streams over all methods in a class, superclasses and (super)interfaces. duke@435: // Streaming is done in reverse order (subclasses first, methods in reverse order) duke@435: // Usage: duke@435: // duke@435: // for (MethodStream st(k, false, false); !st.eos(); st.next()) { duke@435: // methodOop m = st.method(); duke@435: // ... duke@435: // } duke@435: duke@435: class MethodStream : public KlassStream { duke@435: private: duke@435: int length() const { return methods()->length(); } duke@435: objArrayOop methods() const { return _klass->methods(); } duke@435: public: duke@435: MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only) duke@435: : KlassStream(klass, local_only, classes_only) { duke@435: _index = length(); duke@435: next(); duke@435: } duke@435: duke@435: void next() { _index--; } duke@435: methodOop method() const { return methodOop(methods()->obj_at(index())); } duke@435: }; duke@435: duke@435: duke@435: // A FieldStream streams over all fields in a class, superclasses and (super)interfaces. duke@435: // Streaming is done in reverse order (subclasses first, fields in reverse order) duke@435: // Usage: duke@435: // duke@435: // for (FieldStream st(k, false, false); !st.eos(); st.next()) { duke@435: // symbolOop field_name = st.name(); duke@435: // ... duke@435: // } duke@435: duke@435: duke@435: class FieldStream : public KlassStream { duke@435: private: duke@435: int length() const { return fields()->length(); } duke@435: constantPoolOop constants() const { return _klass->constants(); } duke@435: protected: duke@435: typeArrayOop fields() const { return _klass->fields(); } duke@435: public: duke@435: FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) duke@435: : KlassStream(klass, local_only, classes_only) { duke@435: _index = length(); duke@435: next(); duke@435: } duke@435: duke@435: void next() { _index -= instanceKlass::next_offset; } duke@435: duke@435: // Accessors for current field duke@435: AccessFlags access_flags() const { duke@435: AccessFlags flags; duke@435: flags.set_flags(fields()->ushort_at(index() + instanceKlass::access_flags_offset)); duke@435: return flags; duke@435: } duke@435: symbolOop name() const { duke@435: int name_index = fields()->ushort_at(index() + instanceKlass::name_index_offset); duke@435: return constants()->symbol_at(name_index); duke@435: } duke@435: symbolOop signature() const { duke@435: int signature_index = fields()->ushort_at(index() + duke@435: instanceKlass::signature_index_offset); duke@435: return constants()->symbol_at(signature_index); duke@435: } duke@435: // missing: initval() duke@435: int offset() const { duke@435: return _klass->offset_from_fields( index() ); duke@435: } duke@435: }; duke@435: duke@435: class FilteredField { duke@435: private: duke@435: klassOop _klass; duke@435: int _field_offset; duke@435: duke@435: public: duke@435: FilteredField(klassOop klass, int field_offset) { duke@435: _klass = klass; duke@435: _field_offset = field_offset; duke@435: } duke@435: klassOop klass() { return _klass; } duke@435: oop* klass_addr() { return (oop*) &_klass; } duke@435: int field_offset() { return _field_offset; } duke@435: }; duke@435: duke@435: class FilteredFieldsMap : AllStatic { duke@435: private: duke@435: static GrowableArray *_filtered_fields; duke@435: public: duke@435: static void initialize(); duke@435: static bool is_filtered_field(klassOop klass, int field_offset) { duke@435: for (int i=0; i < _filtered_fields->length(); i++) { duke@435: if (klass == _filtered_fields->at(i)->klass() && duke@435: field_offset == _filtered_fields->at(i)->field_offset()) { duke@435: return true; duke@435: } duke@435: } duke@435: return false; duke@435: } duke@435: static int filtered_fields_count(klassOop klass, bool local_only) { duke@435: int nflds = 0; duke@435: for (int i=0; i < _filtered_fields->length(); i++) { duke@435: if (local_only && klass == _filtered_fields->at(i)->klass()) { duke@435: nflds++; duke@435: } else if (klass->klass_part()->is_subtype_of(_filtered_fields->at(i)->klass())) { duke@435: nflds++; duke@435: } duke@435: } duke@435: return nflds; duke@435: } duke@435: // GC support. duke@435: static void klasses_oops_do(OopClosure* f) { duke@435: for (int i = 0; i < _filtered_fields->length(); i++) { duke@435: f->do_oop((oop*)_filtered_fields->at(i)->klass_addr()); duke@435: } duke@435: } duke@435: }; duke@435: duke@435: duke@435: // A FilteredFieldStream streams over all fields in a class, superclasses and duke@435: // (super)interfaces. Streaming is done in reverse order (subclasses first, duke@435: // fields in reverse order) duke@435: // duke@435: // Usage: duke@435: // duke@435: // for (FilteredFieldStream st(k, false, false); !st.eos(); st.next()) { duke@435: // symbolOop field_name = st.name(); duke@435: // ... duke@435: // } duke@435: duke@435: class FilteredFieldStream : public FieldStream { duke@435: private: duke@435: int _filtered_fields_count; duke@435: bool has_filtered_field() { return (_filtered_fields_count > 0); } duke@435: duke@435: public: duke@435: FilteredFieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) duke@435: : FieldStream(klass, local_only, classes_only) { duke@435: _filtered_fields_count = FilteredFieldsMap::filtered_fields_count((klassOop)klass(), local_only); duke@435: } duke@435: int field_count(); duke@435: void next() { duke@435: _index -= instanceKlass::next_offset; duke@435: if (has_filtered_field()) { duke@435: while (_index >=0 && FilteredFieldsMap::is_filtered_field((klassOop)_klass(), offset())) { duke@435: _index -= instanceKlass::next_offset; duke@435: } duke@435: } duke@435: } duke@435: };