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
};


// 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 {
153 154
  friend class VMStructs;

D
duke 已提交
155 156 157 158 159 160
 public:
  // size in words
  static int size() {
    return sizeof(vtableEntry) / sizeof(HeapWord);
  }
  static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); }
161
  Method* method() const    { return _method; }
D
duke 已提交
162 163

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

  friend class klassVtable;
};


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

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

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

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

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

204 205
  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 已提交
206

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

  // 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:
220
  Method* _method;
D
duke 已提交
221 222

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

  void clear()             { _method = NULL; }

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

  // 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 ---
240
//    Klass* of interface 1             \
D
duke 已提交
241 242
//    offset to vtable from start of oop  / offset table entry
//    ...
243
//    Klass* of interface n             \
D
duke 已提交
244 245
//    offset to vtable from start of oop  / offset table entry
//    --- vtable for interface 1 ---
246
//    Method*                             \
D
duke 已提交
247 248
//    compiler entry point                / method table entry
//    ...
249
//    Method*                             \
D
duke 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
//    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]; }

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

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

  // Updates
277
  void initialize_with_method(Method* m);
D
duke 已提交
278

279
#if INCLUDE_JVMTI
D
duke 已提交
280 281 282 283 284 285
  // 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.
286
  void adjust_method_entries(Method** old_methods, Method** new_methods,
D
duke 已提交
287
                             int methods_length, bool * trace_name_printed);
288 289 290
  bool check_no_old_or_obsolete_entries();
  void dump_itable();
#endif // INCLUDE_JVMTI
D
duke 已提交
291 292

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

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

  // 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; })
};
316 317

#endif // SHARE_VM_OOPS_KLASSVTABLE_HPP