0
|
1 /*
|
|
2 * Copyright 1999-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 // A KlassStream is an abstract stream for streaming over self, superclasses
|
|
26 // and (super)interfaces. Streaming is done in reverse order (subclasses first,
|
|
27 // interfaces last).
|
|
28 //
|
|
29 // for (KlassStream st(k, false, false); !st.eos(); st.next()) {
|
|
30 // klassOop k = st.klass();
|
|
31 // ...
|
|
32 // }
|
|
33
|
|
34 class KlassStream VALUE_OBJ_CLASS_SPEC {
|
|
35 protected:
|
|
36 instanceKlassHandle _klass; // current klass/interface iterated over
|
|
37 objArrayHandle _interfaces; // transitive interfaces for initial class
|
|
38 int _interface_index; // current interface being processed
|
|
39 bool _local_only; // process initial class/interface only
|
|
40 bool _classes_only; // process classes only (no interfaces)
|
|
41 int _index;
|
|
42
|
|
43 virtual int length() const = 0;
|
|
44
|
|
45 public:
|
|
46 // constructor
|
|
47 KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only);
|
|
48
|
|
49 // testing
|
|
50 bool eos();
|
|
51
|
|
52 // iterating
|
|
53 virtual void next() = 0;
|
|
54
|
|
55 // accessors
|
|
56 instanceKlassHandle klass() const { return _klass; }
|
|
57 int index() const { return _index; }
|
|
58 };
|
|
59
|
|
60
|
|
61 // A MethodStream streams over all methods in a class, superclasses and (super)interfaces.
|
|
62 // Streaming is done in reverse order (subclasses first, methods in reverse order)
|
|
63 // Usage:
|
|
64 //
|
|
65 // for (MethodStream st(k, false, false); !st.eos(); st.next()) {
|
|
66 // methodOop m = st.method();
|
|
67 // ...
|
|
68 // }
|
|
69
|
|
70 class MethodStream : public KlassStream {
|
|
71 private:
|
|
72 int length() const { return methods()->length(); }
|
|
73 objArrayOop methods() const { return _klass->methods(); }
|
|
74 public:
|
|
75 MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only)
|
|
76 : KlassStream(klass, local_only, classes_only) {
|
|
77 _index = length();
|
|
78 next();
|
|
79 }
|
|
80
|
|
81 void next() { _index--; }
|
|
82 methodOop method() const { return methodOop(methods()->obj_at(index())); }
|
|
83 };
|
|
84
|
|
85
|
|
86 // A FieldStream streams over all fields in a class, superclasses and (super)interfaces.
|
|
87 // Streaming is done in reverse order (subclasses first, fields in reverse order)
|
|
88 // Usage:
|
|
89 //
|
|
90 // for (FieldStream st(k, false, false); !st.eos(); st.next()) {
|
|
91 // symbolOop field_name = st.name();
|
|
92 // ...
|
|
93 // }
|
|
94
|
|
95
|
|
96 class FieldStream : public KlassStream {
|
|
97 private:
|
|
98 int length() const { return fields()->length(); }
|
|
99 constantPoolOop constants() const { return _klass->constants(); }
|
|
100 protected:
|
|
101 typeArrayOop fields() const { return _klass->fields(); }
|
|
102 public:
|
|
103 FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
|
|
104 : KlassStream(klass, local_only, classes_only) {
|
|
105 _index = length();
|
|
106 next();
|
|
107 }
|
|
108
|
|
109 void next() { _index -= instanceKlass::next_offset; }
|
|
110
|
|
111 // Accessors for current field
|
|
112 AccessFlags access_flags() const {
|
|
113 AccessFlags flags;
|
|
114 flags.set_flags(fields()->ushort_at(index() + instanceKlass::access_flags_offset));
|
|
115 return flags;
|
|
116 }
|
|
117 symbolOop name() const {
|
|
118 int name_index = fields()->ushort_at(index() + instanceKlass::name_index_offset);
|
|
119 return constants()->symbol_at(name_index);
|
|
120 }
|
|
121 symbolOop signature() const {
|
|
122 int signature_index = fields()->ushort_at(index() +
|
|
123 instanceKlass::signature_index_offset);
|
|
124 return constants()->symbol_at(signature_index);
|
|
125 }
|
|
126 // missing: initval()
|
|
127 int offset() const {
|
|
128 return _klass->offset_from_fields( index() );
|
|
129 }
|
|
130 };
|
|
131
|
|
132 class FilteredField {
|
|
133 private:
|
|
134 klassOop _klass;
|
|
135 int _field_offset;
|
|
136
|
|
137 public:
|
|
138 FilteredField(klassOop klass, int field_offset) {
|
|
139 _klass = klass;
|
|
140 _field_offset = field_offset;
|
|
141 }
|
|
142 klassOop klass() { return _klass; }
|
|
143 oop* klass_addr() { return (oop*) &_klass; }
|
|
144 int field_offset() { return _field_offset; }
|
|
145 };
|
|
146
|
|
147 class FilteredFieldsMap : AllStatic {
|
|
148 private:
|
|
149 static GrowableArray<FilteredField *> *_filtered_fields;
|
|
150 public:
|
|
151 static void initialize();
|
|
152 static bool is_filtered_field(klassOop klass, int field_offset) {
|
|
153 for (int i=0; i < _filtered_fields->length(); i++) {
|
|
154 if (klass == _filtered_fields->at(i)->klass() &&
|
|
155 field_offset == _filtered_fields->at(i)->field_offset()) {
|
|
156 return true;
|
|
157 }
|
|
158 }
|
|
159 return false;
|
|
160 }
|
|
161 static int filtered_fields_count(klassOop klass, bool local_only) {
|
|
162 int nflds = 0;
|
|
163 for (int i=0; i < _filtered_fields->length(); i++) {
|
|
164 if (local_only && klass == _filtered_fields->at(i)->klass()) {
|
|
165 nflds++;
|
|
166 } else if (klass->klass_part()->is_subtype_of(_filtered_fields->at(i)->klass())) {
|
|
167 nflds++;
|
|
168 }
|
|
169 }
|
|
170 return nflds;
|
|
171 }
|
|
172 // GC support.
|
|
173 static void klasses_oops_do(OopClosure* f) {
|
|
174 for (int i = 0; i < _filtered_fields->length(); i++) {
|
|
175 f->do_oop((oop*)_filtered_fields->at(i)->klass_addr());
|
|
176 }
|
|
177 }
|
|
178 };
|
|
179
|
|
180
|
|
181 // A FilteredFieldStream streams over all fields in a class, superclasses and
|
|
182 // (super)interfaces. Streaming is done in reverse order (subclasses first,
|
|
183 // fields in reverse order)
|
|
184 //
|
|
185 // Usage:
|
|
186 //
|
|
187 // for (FilteredFieldStream st(k, false, false); !st.eos(); st.next()) {
|
|
188 // symbolOop field_name = st.name();
|
|
189 // ...
|
|
190 // }
|
|
191
|
|
192 class FilteredFieldStream : public FieldStream {
|
|
193 private:
|
|
194 int _filtered_fields_count;
|
|
195 bool has_filtered_field() { return (_filtered_fields_count > 0); }
|
|
196
|
|
197 public:
|
|
198 FilteredFieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
|
|
199 : FieldStream(klass, local_only, classes_only) {
|
|
200 _filtered_fields_count = FilteredFieldsMap::filtered_fields_count((klassOop)klass(), local_only);
|
|
201 }
|
|
202 int field_count();
|
|
203 void next() {
|
|
204 _index -= instanceKlass::next_offset;
|
|
205 if (has_filtered_field()) {
|
|
206 while (_index >=0 && FilteredFieldsMap::is_filtered_field((klassOop)_klass(), offset())) {
|
|
207 _index -= instanceKlass::next_offset;
|
|
208 }
|
|
209 }
|
|
210 }
|
|
211 };
|