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