klassVtable.hpp 12.6 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30 31 32
#ifndef SHARE_VM_OOPS_KLASSVTABLE_HPP
#define SHARE_VM_OOPS_KLASSVTABLE_HPP

#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/handles.hpp"
#include "utilities/growableArray.hpp"

33
// A klassVtable abstracts the variable-length vtable that is embedded in InstanceKlass
34
// and ArrayKlass.  klassVtable objects are used just as convenient transient accessors to the vtable,
D
duke 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
// not to actually hold the vtable data.
// Note: the klassVtable should not be accessed before the class has been verified
// (until that point, the vtable is uninitialized).

// Currently a klassVtable contains a direct reference to the vtable data, and is therefore
// not preserved across GCs.

class vtableEntry;

class klassVtable : public ResourceObj {
  KlassHandle  _klass;            // my klass
  int          _tableOffset;      // offset of start of vtable data within klass
  int          _length;           // length of vtable (number of entries)
#ifndef PRODUCT
  int          _verify_count;     // to make verify faster
#endif

  // Ordering important, so greater_than (>) can be used as an merge operator.
  enum AccessType {
    acc_private         = 0,
    acc_package_private = 1,
    acc_publicprotected = 2
  };

 public:
  klassVtable(KlassHandle h_klass, void* base, int length) : _klass(h_klass) {
    _tableOffset = (address)base - (address)h_klass(); _length = length;
  }

  // accessors
  vtableEntry* table() const      { return (vtableEntry*)(address(_klass()) + _tableOffset); }
  KlassHandle klass() const       { return _klass;  }
  int length() const              { return _length; }
68 69 70
  inline Method* method_at(int i) const;
  inline Method* unchecked_method_at(int i) const;
  inline Method** adr_method_at(int i) const;
D
duke 已提交
71 72

  // searching; all methods return -1 if not found
73
  int index_of(Method* m) const                         { return index_of(m, _length); }
74
  int index_of_miranda(Symbol* name, Symbol* signature);
D
duke 已提交
75 76 77

  void initialize_vtable(bool checkconstraints, TRAPS);   // initialize vtable of a new klass

78 79 80 81 82 83 84 85 86
  // CDS/RedefineClasses support - clear vtables so they can be reinitialized
  // at dump time.  Clearing gives us an easy way to tell if the vtable has
  // already been reinitialized at dump time (see dump.cpp).  Vtables can
  // be initialized at run time by RedefineClasses so dumping the right order
  // is necessary.
  void clear_vtable();
  bool is_initialized();

  // computes vtable length (in words) and the number of miranda methods
87 88 89 90 91
  static void compute_vtable_size_and_num_mirandas(
      int* vtable_length, int* num_new_mirandas,
      GrowableArray<Method*>* all_mirandas, Klass* super,
      Array<Method*>* methods, AccessFlags class_flags, Handle classloader,
      Symbol* classname, Array<Klass*>* local_interfaces, TRAPS);
D
duke 已提交
92

93
#if INCLUDE_JVMTI
D
duke 已提交
94 95 96 97 98 99
  // RedefineClasses() API support:
  // If any entry of this vtable points to any of old_methods,
  // replace it with the corresponding new_method.
  // trace_name_printed is set to true if the current call has
  // printed the klass name so that other routines in the adjust_*
  // group don't print the klass name.
100
  void adjust_method_entries(Method** old_methods, Method** new_methods,
D
duke 已提交
101
                             int methods_length, bool * trace_name_printed);
102 103 104
  bool check_no_old_or_obsolete_entries();
  void dump_vtable();
#endif // INCLUDE_JVMTI
D
duke 已提交
105 106 107 108 109 110 111 112 113

  // Debugging code
  void print()                                              PRODUCT_RETURN;
  void verify(outputStream* st, bool force = false);
  static void print_statistics()                            PRODUCT_RETURN;

 protected:
  friend class vtableEntry;
 private:
114
  enum { VTABLE_TRANSITIVE_OVERRIDE_VERSION = 51 } ;
D
duke 已提交
115 116
  void copy_vtable_to(vtableEntry* start);
  int  initialize_from_super(KlassHandle super);
117 118 119
  int  index_of(Method* m, int len) const; // same as index_of, but search only up to len
  void put_method_at(Method* m, int index);
  static bool needs_new_vtable_entry(methodHandle m, Klass* super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS);
D
duke 已提交
120

121 122
  bool update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS);
 InstanceKlass* find_transitive_override(InstanceKlass* initialsuper, methodHandle target_method, int vtable_index,
123
                                         Handle target_loader, Symbol* target_classname, Thread* THREAD);
D
duke 已提交
124 125 126

  // support for miranda methods
  bool is_miranda_entry_at(int i);
127
  void fill_in_mirandas(int* initialized);
128
  static bool is_miranda(Method* m, Array<Method*>* class_methods, Klass* super);
129 130 131 132 133 134 135 136 137
  static void add_new_mirandas_to_lists(
      GrowableArray<Method*>* new_mirandas,
      GrowableArray<Method*>* all_mirandas,
      Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
      Klass* super);
  static void get_mirandas(
      GrowableArray<Method*>* new_mirandas,
      GrowableArray<Method*>* all_mirandas, Klass* super,
      Array<Method*>* class_methods, Array<Klass*>* local_interfaces);
D
duke 已提交
138 139

  void verify_against(outputStream* st, klassVtable* vt, int index);
140
  inline InstanceKlass* ik() const;
D
duke 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
};


// private helper class for klassVtable
// description of entry points:
//    destination is interpreted:
//      from_compiled_code_entry_point -> c2iadapter
//      from_interpreter_entry_point   -> interpreter entry point
//    destination is compiled:
//      from_compiled_code_entry_point -> nmethod entry point
//      from_interpreter_entry_point   -> i2cadapter
class vtableEntry VALUE_OBJ_CLASS_SPEC {
 public:
  // size in words
  static int size() {
    return sizeof(vtableEntry) / sizeof(HeapWord);
  }
  static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); }
159
  Method* method() const    { return _method; }
D
duke 已提交
160 161

 private:
162 163
  Method* _method;
  void set(Method* method)  { assert(method != NULL, "use clear"); _method = method; }
D
duke 已提交
164 165 166 167 168 169 170 171
  void clear()                { _method = NULL; }
  void print()                                        PRODUCT_RETURN;
  void verify(klassVtable* vt, outputStream* st);

  friend class klassVtable;
};


172
inline Method* klassVtable::method_at(int i) const {
D
duke 已提交
173 174
  assert(i >= 0 && i < _length, "index out of bounds");
  assert(table()[i].method() != NULL, "should not be null");
175
  assert(((Metadata*)table()[i].method())->is_method(), "should be method");
D
duke 已提交
176 177 178
  return table()[i].method();
}

179
inline Method* klassVtable::unchecked_method_at(int i) const {
D
duke 已提交
180 181 182 183
  assert(i >= 0 && i < _length, "index out of bounds");
  return table()[i].method();
}

184
inline Method** klassVtable::adr_method_at(int i) const {
D
duke 已提交
185 186
  // Allow one past the last entry to be referenced; useful for loop bounds.
  assert(i >= 0 && i <= _length, "index out of bounds");
187
  return (Method**)(address(table() + i) + vtableEntry::method_offset_in_bytes());
D
duke 已提交
188 189 190 191 192 193 194 195
}

// --------------------------------------------------------------------------------
class klassItable;
class itableMethodEntry;

class itableOffsetEntry VALUE_OBJ_CLASS_SPEC {
 private:
196
  Klass* _interface;
D
duke 已提交
197 198
  int      _offset;
 public:
199
  Klass* interface_klass() const { return _interface; }
D
duke 已提交
200 201
  int      offset() const          { return _offset; }

202 203
  static itableMethodEntry* method_entry(Klass* k, int offset) { return (itableMethodEntry*)(((address)k) + offset); }
  itableMethodEntry* first_method_entry(Klass* k)              { return method_entry(k, _offset); }
D
duke 已提交
204

205
  void initialize(Klass* interf, int offset) { _interface = interf; _offset = offset; }
D
duke 已提交
206 207 208 209 210 211 212 213 214 215 216 217

  // Static size and offset accessors
  static int size()                       { return sizeof(itableOffsetEntry) / HeapWordSize; }    // size in words
  static int interface_offset_in_bytes()  { return offset_of(itableOffsetEntry, _interface); }
  static int offset_offset_in_bytes()     { return offset_of(itableOffsetEntry, _offset); }

  friend class klassItable;
};


class itableMethodEntry VALUE_OBJ_CLASS_SPEC {
 private:
218
  Method* _method;
D
duke 已提交
219 220

 public:
221
  Method* method() const { return _method; }
D
duke 已提交
222 223 224

  void clear()             { _method = NULL; }

225
  void initialize(Method* method);
D
duke 已提交
226 227 228 229 230 231 232 233 234 235 236 237

  // Static size and offset accessors
  static int size()                         { return sizeof(itableMethodEntry) / HeapWordSize; }  // size in words
  static int method_offset_in_bytes()       { return offset_of(itableMethodEntry, _method); }

  friend class klassItable;
};

//
// Format of an itable
//
//    ---- offset table ---
238
//    Klass* of interface 1             \
D
duke 已提交
239 240
//    offset to vtable from start of oop  / offset table entry
//    ...
241
//    Klass* of interface n             \
D
duke 已提交
242 243
//    offset to vtable from start of oop  / offset table entry
//    --- vtable for interface 1 ---
244
//    Method*                             \
D
duke 已提交
245 246
//    compiler entry point                / method table entry
//    ...
247
//    Method*                             \
D
duke 已提交
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
//    compiler entry point                / method table entry
//    -- vtable for interface 2 ---
//    ...
//
class klassItable : public ResourceObj {
 private:
  instanceKlassHandle  _klass;             // my klass
  int                  _table_offset;      // offset of start of itable data within klass (in words)
  int                  _size_offset_table; // size of offset table (in itableOffset entries)
  int                  _size_method_table; // size of methodtable (in itableMethodEntry entries)

  void initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS);
 public:
  klassItable(instanceKlassHandle klass);

  itableOffsetEntry* offset_entry(int i) { assert(0 <= i && i <= _size_offset_table, "index out of bounds");
                                           return &((itableOffsetEntry*)vtable_start())[i]; }

  itableMethodEntry* method_entry(int i) { assert(0 <= i && i <= _size_method_table, "index out of bounds");
                                           return &((itableMethodEntry*)method_start())[i]; }

269
  int size_offset_table()                { return _size_offset_table; }
D
duke 已提交
270 271 272 273 274

  // Initialization
  void initialize_itable(bool checkconstraints, TRAPS);

  // Updates
275
  void initialize_with_method(Method* m);
D
duke 已提交
276

277
#if INCLUDE_JVMTI
D
duke 已提交
278 279 280 281 282 283
  // RedefineClasses() API support:
  // if any entry of this itable points to any of old_methods,
  // replace it with the corresponding new_method.
  // trace_name_printed is set to true if the current call has
  // printed the klass name so that other routines in the adjust_*
  // group don't print the klass name.
284
  void adjust_method_entries(Method** old_methods, Method** new_methods,
D
duke 已提交
285
                             int methods_length, bool * trace_name_printed);
286 287 288
  bool check_no_old_or_obsolete_entries();
  void dump_itable();
#endif // INCLUDE_JVMTI
D
duke 已提交
289 290

  // Setup of itable
291
  static int compute_itable_size(Array<Klass*>* transitive_interfaces);
D
duke 已提交
292 293 294
  static void setup_itable_offset_table(instanceKlassHandle klass);

  // Resolving of method to index
295
  static int compute_itable_index(Method* m);
296
  // ...and back again:
297
  static Method* method_for_itable_index(Klass* klass, int itable_index);
D
duke 已提交
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313

  // Debugging/Statistics
  static void print_statistics() PRODUCT_RETURN;
 private:
  intptr_t* vtable_start() const { return ((intptr_t*)_klass()) + _table_offset; }
  intptr_t* method_start() const { return vtable_start() + _size_offset_table * itableOffsetEntry::size(); }

  // Helper methods
  static int  calc_itable_size(int num_interfaces, int num_methods) { return (num_interfaces * itableOffsetEntry::size()) + (num_methods * itableMethodEntry::size()); }

  // Statistics
  NOT_PRODUCT(static int  _total_classes;)   // Total no. of classes with itables
  NOT_PRODUCT(static long _total_size;)      // Total no. of bytes used for itables

  static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
};
314 315

#endif // SHARE_VM_OOPS_KLASSVTABLE_HPP