klassVtable.hpp revision 0:a61af66fc99e
1/*
2 * Copyright 1997-2006 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 klassVtable abstracts the variable-length vtable that is embedded in instanceKlass
26// and arrayKlass.  klassVtable objects are used just as convenient transient accessors to the vtable,
27// not to actually hold the vtable data.
28// Note: the klassVtable should not be accessed before the class has been verified
29// (until that point, the vtable is uninitialized).
30
31// Currently a klassVtable contains a direct reference to the vtable data, and is therefore
32// not preserved across GCs.
33
34class vtableEntry;
35
36class klassVtable : public ResourceObj {
37  KlassHandle  _klass;            // my klass
38  int          _tableOffset;      // offset of start of vtable data within klass
39  int          _length;           // length of vtable (number of entries)
40#ifndef PRODUCT
41  int          _verify_count;     // to make verify faster
42#endif
43
44  // Ordering important, so greater_than (>) can be used as an merge operator.
45  enum AccessType {
46    acc_private         = 0,
47    acc_package_private = 1,
48    acc_publicprotected = 2
49  };
50
51 public:
52  klassVtable(KlassHandle h_klass, void* base, int length) : _klass(h_klass) {
53    _tableOffset = (address)base - (address)h_klass(); _length = length;
54  }
55
56  // accessors
57  vtableEntry* table() const      { return (vtableEntry*)(address(_klass()) + _tableOffset); }
58  KlassHandle klass() const       { return _klass;  }
59  int length() const              { return _length; }
60  inline methodOop method_at(int i) const;
61  inline methodOop unchecked_method_at(int i) const;
62  inline oop*      adr_method_at(int i) const;
63
64  // searching; all methods return -1 if not found
65  int index_of(methodOop m) const                         { return index_of(m, _length); }
66  int index_of_miranda(symbolOop name, symbolOop signature);
67
68  void initialize_vtable(bool checkconstraints, TRAPS);   // initialize vtable of a new klass
69
70  // conputes vtable length (in words) and the number of miranda methods
71  static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods,
72                                                   klassOop super, objArrayOop methods,
73                                                   AccessFlags class_flags, oop classloader,
74                                                   symbolOop classname, objArrayOop local_interfaces);
75
76  // RedefineClasses() API support:
77  // If any entry of this vtable points to any of old_methods,
78  // replace it with the corresponding new_method.
79  // trace_name_printed is set to true if the current call has
80  // printed the klass name so that other routines in the adjust_*
81  // group don't print the klass name.
82  void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
83                             int methods_length, bool * trace_name_printed);
84
85  // Garbage collection
86  void oop_follow_contents();
87  void oop_adjust_pointers();
88
89#ifndef SERIALGC
90  // Parallel Old
91  void oop_follow_contents(ParCompactionManager* cm);
92  void oop_update_pointers(ParCompactionManager* cm);
93  void oop_update_pointers(ParCompactionManager* cm,
94                           HeapWord* beg_addr, HeapWord* end_addr);
95#endif // SERIALGC
96
97  // Iterators
98  void oop_oop_iterate(OopClosure* blk);
99  void oop_oop_iterate_m(OopClosure* blk, MemRegion mr);
100
101  // Debugging code
102  void print()                                              PRODUCT_RETURN;
103  void verify(outputStream* st, bool force = false);
104  static void print_statistics()                            PRODUCT_RETURN;
105
106#ifndef PRODUCT
107  bool check_no_old_entries();
108  void dump_vtable();
109#endif
110
111 protected:
112  friend class vtableEntry;
113 private:
114  void copy_vtable_to(vtableEntry* start);
115  int  initialize_from_super(KlassHandle super);
116  int  index_of(methodOop m, int len) const; // same as index_of, but search only up to len
117  void put_method_at(methodOop m, int index);
118  static bool needs_new_vtable_entry(methodOop m, klassOop super, oop classloader, symbolOop classname, AccessFlags access_flags);
119  AccessType vtable_accessibility_at(int i);
120
121  bool update_super_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS);
122
123  // support for miranda methods
124  bool is_miranda_entry_at(int i);
125  void fill_in_mirandas(int& initialized);
126  static bool is_miranda(methodOop m, objArrayOop class_methods, klassOop super);
127  static void add_new_mirandas_to_list(GrowableArray<methodOop>* list_of_current_mirandas, objArrayOop current_interface_methods, objArrayOop class_methods, klassOop super);
128  static void get_mirandas(GrowableArray<methodOop>* mirandas, klassOop super, objArrayOop class_methods, objArrayOop local_interfaces);
129  static int get_num_mirandas(klassOop super, objArrayOop class_methods, objArrayOop local_interfaces);
130
131
132  void verify_against(outputStream* st, klassVtable* vt, int index);
133  inline instanceKlass* ik() const;
134};
135
136
137// private helper class for klassVtable
138// description of entry points:
139//    destination is interpreted:
140//      from_compiled_code_entry_point -> c2iadapter
141//      from_interpreter_entry_point   -> interpreter entry point
142//    destination is compiled:
143//      from_compiled_code_entry_point -> nmethod entry point
144//      from_interpreter_entry_point   -> i2cadapter
145class vtableEntry VALUE_OBJ_CLASS_SPEC {
146 public:
147  // size in words
148  static int size() {
149    return sizeof(vtableEntry) / sizeof(HeapWord);
150  }
151  static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); }
152  methodOop method() const    { return _method; }
153
154 private:
155  methodOop _method;
156  void set(methodOop method)  { assert(method != NULL, "use clear"); _method = method; }
157  void clear()                { _method = NULL; }
158  void print()                                        PRODUCT_RETURN;
159  void verify(klassVtable* vt, outputStream* st);
160
161  friend class klassVtable;
162};
163
164
165inline methodOop klassVtable::method_at(int i) const {
166  assert(i >= 0 && i < _length, "index out of bounds");
167  assert(table()[i].method() != NULL, "should not be null");
168  assert(oop(table()[i].method())->is_method(), "should be method");
169  return table()[i].method();
170}
171
172inline methodOop klassVtable::unchecked_method_at(int i) const {
173  assert(i >= 0 && i < _length, "index out of bounds");
174  return table()[i].method();
175}
176
177inline oop* klassVtable::adr_method_at(int i) const {
178  // Allow one past the last entry to be referenced; useful for loop bounds.
179  assert(i >= 0 && i <= _length, "index out of bounds");
180  return (oop*)(address(table() + i) + vtableEntry::method_offset_in_bytes());
181}
182
183// --------------------------------------------------------------------------------
184class klassItable;
185class itableMethodEntry;
186
187class itableOffsetEntry VALUE_OBJ_CLASS_SPEC {
188 private:
189  klassOop _interface;
190  int      _offset;
191 public:
192  klassOop interface_klass() const { return _interface; }
193  int      offset() const          { return _offset; }
194
195  static itableMethodEntry* method_entry(klassOop k, int offset) { return (itableMethodEntry*)(((address)k) + offset); }
196  itableMethodEntry* first_method_entry(klassOop k)              { return method_entry(k, _offset); }
197
198  void initialize(klassOop interf, int offset) { _interface = interf; _offset = offset; }
199
200  // Static size and offset accessors
201  static int size()                       { return sizeof(itableOffsetEntry) / HeapWordSize; }    // size in words
202  static int interface_offset_in_bytes()  { return offset_of(itableOffsetEntry, _interface); }
203  static int offset_offset_in_bytes()     { return offset_of(itableOffsetEntry, _offset); }
204
205  friend class klassItable;
206};
207
208
209class itableMethodEntry VALUE_OBJ_CLASS_SPEC {
210 private:
211  methodOop _method;
212
213 public:
214  methodOop method() const { return _method; }
215
216  void clear()             { _method = NULL; }
217
218  void initialize(methodOop method);
219
220  // Static size and offset accessors
221  static int size()                         { return sizeof(itableMethodEntry) / HeapWordSize; }  // size in words
222  static int method_offset_in_bytes()       { return offset_of(itableMethodEntry, _method); }
223
224  friend class klassItable;
225};
226
227//
228// Format of an itable
229//
230//    ---- offset table ---
231//    klassOop of interface 1             \
232//    offset to vtable from start of oop  / offset table entry
233//    ...
234//    klassOop of interface n             \
235//    offset to vtable from start of oop  / offset table entry
236//    --- vtable for interface 1 ---
237//    methodOop                           \
238//    compiler entry point                / method table entry
239//    ...
240//    methodOop                           \
241//    compiler entry point                / method table entry
242//    -- vtable for interface 2 ---
243//    ...
244//
245class klassItable : public ResourceObj {
246 private:
247  instanceKlassHandle  _klass;             // my klass
248  int                  _table_offset;      // offset of start of itable data within klass (in words)
249  int                  _size_offset_table; // size of offset table (in itableOffset entries)
250  int                  _size_method_table; // size of methodtable (in itableMethodEntry entries)
251
252  void initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS);
253 public:
254  klassItable(instanceKlassHandle klass);
255
256  itableOffsetEntry* offset_entry(int i) { assert(0 <= i && i <= _size_offset_table, "index out of bounds");
257                                           return &((itableOffsetEntry*)vtable_start())[i]; }
258
259  itableMethodEntry* method_entry(int i) { assert(0 <= i && i <= _size_method_table, "index out of bounds");
260                                           return &((itableMethodEntry*)method_start())[i]; }
261
262  int nof_interfaces()                   { return _size_offset_table; }
263
264  // Initialization
265  void initialize_itable(bool checkconstraints, TRAPS);
266
267  // Updates
268  void initialize_with_method(methodOop m);
269
270  // RedefineClasses() API support:
271  // if any entry of this itable points to any of old_methods,
272  // replace it with the corresponding new_method.
273  // trace_name_printed is set to true if the current call has
274  // printed the klass name so that other routines in the adjust_*
275  // group don't print the klass name.
276  void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
277                             int methods_length, bool * trace_name_printed);
278
279  // Garbage collection
280  void oop_follow_contents();
281  void oop_adjust_pointers();
282
283#ifndef SERIALGC
284  // Parallel Old
285  void oop_follow_contents(ParCompactionManager* cm);
286  void oop_update_pointers(ParCompactionManager* cm);
287  void oop_update_pointers(ParCompactionManager* cm,
288                           HeapWord* beg_addr, HeapWord* end_addr);
289#endif // SERIALGC
290
291  // Iterators
292  void oop_oop_iterate(OopClosure* blk);
293  void oop_oop_iterate_m(OopClosure* blk, MemRegion mr);
294
295  // Setup of itable
296  static int compute_itable_size(objArrayHandle transitive_interfaces);
297  static void setup_itable_offset_table(instanceKlassHandle klass);
298
299  // Resolving of method to index
300  static int compute_itable_index(methodOop m);
301
302  // Debugging/Statistics
303  static void print_statistics() PRODUCT_RETURN;
304 private:
305  intptr_t* vtable_start() const { return ((intptr_t*)_klass()) + _table_offset; }
306  intptr_t* method_start() const { return vtable_start() + _size_offset_table * itableOffsetEntry::size(); }
307
308  // Helper methods
309  static int  calc_itable_size(int num_interfaces, int num_methods) { return (num_interfaces * itableOffsetEntry::size()) + (num_methods * itableMethodEntry::size()); }
310
311  // Statistics
312  NOT_PRODUCT(static int  _total_classes;)   // Total no. of classes with itables
313  NOT_PRODUCT(static long _total_size;)      // Total no. of bytes used for itables
314
315  static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
316};
317