Mercurial > hg > truffle
comparison src/share/vm/oops/klassVtable.hpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | 8ce625481709 |
children | d8ce2825b193 |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
28 #include "memory/allocation.hpp" | 28 #include "memory/allocation.hpp" |
29 #include "oops/oopsHierarchy.hpp" | 29 #include "oops/oopsHierarchy.hpp" |
30 #include "runtime/handles.hpp" | 30 #include "runtime/handles.hpp" |
31 #include "utilities/growableArray.hpp" | 31 #include "utilities/growableArray.hpp" |
32 | 32 |
33 // A klassVtable abstracts the variable-length vtable that is embedded in instanceKlass | 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, | 34 // and arrayKlass. klassVtable objects are used just as convenient transient accessors to the vtable, |
35 // not to actually hold the vtable data. | 35 // not to actually hold the vtable data. |
36 // Note: the klassVtable should not be accessed before the class has been verified | 36 // Note: the klassVtable should not be accessed before the class has been verified |
37 // (until that point, the vtable is uninitialized). | 37 // (until that point, the vtable is uninitialized). |
38 | 38 |
63 | 63 |
64 // accessors | 64 // accessors |
65 vtableEntry* table() const { return (vtableEntry*)(address(_klass()) + _tableOffset); } | 65 vtableEntry* table() const { return (vtableEntry*)(address(_klass()) + _tableOffset); } |
66 KlassHandle klass() const { return _klass; } | 66 KlassHandle klass() const { return _klass; } |
67 int length() const { return _length; } | 67 int length() const { return _length; } |
68 inline methodOop method_at(int i) const; | 68 inline Method* method_at(int i) const; |
69 inline methodOop unchecked_method_at(int i) const; | 69 inline Method* unchecked_method_at(int i) const; |
70 inline oop* adr_method_at(int i) const; | 70 inline Method** adr_method_at(int i) const; |
71 | 71 |
72 // searching; all methods return -1 if not found | 72 // searching; all methods return -1 if not found |
73 int index_of(methodOop m) const { return index_of(m, _length); } | 73 int index_of(Method* m) const { return index_of(m, _length); } |
74 int index_of_miranda(Symbol* name, Symbol* signature); | 74 int index_of_miranda(Symbol* name, Symbol* signature); |
75 | 75 |
76 void initialize_vtable(bool checkconstraints, TRAPS); // initialize vtable of a new klass | 76 void initialize_vtable(bool checkconstraints, TRAPS); // initialize vtable of a new klass |
77 | 77 |
78 // CDS/RedefineClasses support - clear vtables so they can be reinitialized | 78 // CDS/RedefineClasses support - clear vtables so they can be reinitialized |
83 void clear_vtable(); | 83 void clear_vtable(); |
84 bool is_initialized(); | 84 bool is_initialized(); |
85 | 85 |
86 // computes vtable length (in words) and the number of miranda methods | 86 // computes vtable length (in words) and the number of miranda methods |
87 static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods, | 87 static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods, |
88 klassOop super, objArrayOop methods, | 88 Klass* super, Array<Method*>* methods, |
89 AccessFlags class_flags, Handle classloader, | 89 AccessFlags class_flags, Handle classloader, |
90 Symbol* classname, objArrayOop local_interfaces, | 90 Symbol* classname, Array<Klass*>* local_interfaces, |
91 TRAPS); | 91 TRAPS); |
92 | 92 |
93 // RedefineClasses() API support: | 93 // RedefineClasses() API support: |
94 // If any entry of this vtable points to any of old_methods, | 94 // If any entry of this vtable points to any of old_methods, |
95 // replace it with the corresponding new_method. | 95 // replace it with the corresponding new_method. |
96 // trace_name_printed is set to true if the current call has | 96 // trace_name_printed is set to true if the current call has |
97 // printed the klass name so that other routines in the adjust_* | 97 // printed the klass name so that other routines in the adjust_* |
98 // group don't print the klass name. | 98 // group don't print the klass name. |
99 void adjust_method_entries(methodOop* old_methods, methodOop* new_methods, | 99 void adjust_method_entries(Method** old_methods, Method** new_methods, |
100 int methods_length, bool * trace_name_printed); | 100 int methods_length, bool * trace_name_printed); |
101 | |
102 // Garbage collection | |
103 void oop_follow_contents(); | |
104 void oop_adjust_pointers(); | |
105 | |
106 #ifndef SERIALGC | |
107 // Parallel Old | |
108 void oop_follow_contents(ParCompactionManager* cm); | |
109 void oop_update_pointers(ParCompactionManager* cm); | |
110 #endif // SERIALGC | |
111 | |
112 // Iterators | |
113 void oop_oop_iterate(OopClosure* blk); | |
114 void oop_oop_iterate_m(OopClosure* blk, MemRegion mr); | |
115 | 101 |
116 // Debugging code | 102 // Debugging code |
117 void print() PRODUCT_RETURN; | 103 void print() PRODUCT_RETURN; |
118 void verify(outputStream* st, bool force = false); | 104 void verify(outputStream* st, bool force = false); |
119 static void print_statistics() PRODUCT_RETURN; | 105 static void print_statistics() PRODUCT_RETURN; |
127 friend class vtableEntry; | 113 friend class vtableEntry; |
128 private: | 114 private: |
129 enum { VTABLE_TRANSITIVE_OVERRIDE_VERSION = 51 } ; | 115 enum { VTABLE_TRANSITIVE_OVERRIDE_VERSION = 51 } ; |
130 void copy_vtable_to(vtableEntry* start); | 116 void copy_vtable_to(vtableEntry* start); |
131 int initialize_from_super(KlassHandle super); | 117 int initialize_from_super(KlassHandle super); |
132 int index_of(methodOop m, int len) const; // same as index_of, but search only up to len | 118 int index_of(Method* m, int len) const; // same as index_of, but search only up to len |
133 void put_method_at(methodOop m, int index); | 119 void put_method_at(Method* m, int index); |
134 static bool needs_new_vtable_entry(methodHandle m, klassOop super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS); | 120 static bool needs_new_vtable_entry(methodHandle m, Klass* super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS); |
135 | 121 |
136 bool update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS); | 122 bool update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS); |
137 instanceKlass* find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, int vtable_index, | 123 InstanceKlass* find_transitive_override(InstanceKlass* initialsuper, methodHandle target_method, int vtable_index, |
138 Handle target_loader, Symbol* target_classname, Thread* THREAD); | 124 Handle target_loader, Symbol* target_classname, Thread* THREAD); |
139 | 125 |
140 // support for miranda methods | 126 // support for miranda methods |
141 bool is_miranda_entry_at(int i); | 127 bool is_miranda_entry_at(int i); |
142 void fill_in_mirandas(int& initialized); | 128 void fill_in_mirandas(int& initialized); |
143 static bool is_miranda(methodOop m, objArrayOop class_methods, klassOop super); | 129 static bool is_miranda(Method* m, Array<Method*>* class_methods, Klass* super); |
144 static void add_new_mirandas_to_list(GrowableArray<methodOop>* list_of_current_mirandas, objArrayOop current_interface_methods, objArrayOop class_methods, klassOop super); | 130 static void add_new_mirandas_to_list(GrowableArray<Method*>* list_of_current_mirandas, Array<Method*>* current_interface_methods, Array<Method*>* class_methods, Klass* super); |
145 static void get_mirandas(GrowableArray<methodOop>* mirandas, klassOop super, objArrayOop class_methods, objArrayOop local_interfaces); | 131 static void get_mirandas(GrowableArray<Method*>* mirandas, Klass* super, Array<Method*>* class_methods, Array<Klass*>* local_interfaces); |
146 static int get_num_mirandas(klassOop super, objArrayOop class_methods, objArrayOop local_interfaces); | 132 static int get_num_mirandas(Klass* super, Array<Method*>* class_methods, Array<Klass*>* local_interfaces); |
147 | 133 |
148 | 134 |
149 void verify_against(outputStream* st, klassVtable* vt, int index); | 135 void verify_against(outputStream* st, klassVtable* vt, int index); |
150 inline instanceKlass* ik() const; | 136 inline InstanceKlass* ik() const; |
151 }; | 137 }; |
152 | 138 |
153 | 139 |
154 // private helper class for klassVtable | 140 // private helper class for klassVtable |
155 // description of entry points: | 141 // description of entry points: |
164 // size in words | 150 // size in words |
165 static int size() { | 151 static int size() { |
166 return sizeof(vtableEntry) / sizeof(HeapWord); | 152 return sizeof(vtableEntry) / sizeof(HeapWord); |
167 } | 153 } |
168 static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); } | 154 static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); } |
169 methodOop method() const { return _method; } | 155 Method* method() const { return _method; } |
170 | 156 |
171 private: | 157 private: |
172 methodOop _method; | 158 Method* _method; |
173 void set(methodOop method) { assert(method != NULL, "use clear"); _method = method; } | 159 void set(Method* method) { assert(method != NULL, "use clear"); _method = method; } |
174 void clear() { _method = NULL; } | 160 void clear() { _method = NULL; } |
175 void print() PRODUCT_RETURN; | 161 void print() PRODUCT_RETURN; |
176 void verify(klassVtable* vt, outputStream* st); | 162 void verify(klassVtable* vt, outputStream* st); |
177 | 163 |
178 friend class klassVtable; | 164 friend class klassVtable; |
179 }; | 165 }; |
180 | 166 |
181 | 167 |
182 inline methodOop klassVtable::method_at(int i) const { | 168 inline Method* klassVtable::method_at(int i) const { |
183 assert(i >= 0 && i < _length, "index out of bounds"); | 169 assert(i >= 0 && i < _length, "index out of bounds"); |
184 assert(table()[i].method() != NULL, "should not be null"); | 170 assert(table()[i].method() != NULL, "should not be null"); |
185 assert(oop(table()[i].method())->is_method(), "should be method"); | 171 assert(((Metadata*)table()[i].method())->is_method(), "should be method"); |
186 return table()[i].method(); | 172 return table()[i].method(); |
187 } | 173 } |
188 | 174 |
189 inline methodOop klassVtable::unchecked_method_at(int i) const { | 175 inline Method* klassVtable::unchecked_method_at(int i) const { |
190 assert(i >= 0 && i < _length, "index out of bounds"); | 176 assert(i >= 0 && i < _length, "index out of bounds"); |
191 return table()[i].method(); | 177 return table()[i].method(); |
192 } | 178 } |
193 | 179 |
194 inline oop* klassVtable::adr_method_at(int i) const { | 180 inline Method** klassVtable::adr_method_at(int i) const { |
195 // Allow one past the last entry to be referenced; useful for loop bounds. | 181 // Allow one past the last entry to be referenced; useful for loop bounds. |
196 assert(i >= 0 && i <= _length, "index out of bounds"); | 182 assert(i >= 0 && i <= _length, "index out of bounds"); |
197 return (oop*)(address(table() + i) + vtableEntry::method_offset_in_bytes()); | 183 return (Method**)(address(table() + i) + vtableEntry::method_offset_in_bytes()); |
198 } | 184 } |
199 | 185 |
200 // -------------------------------------------------------------------------------- | 186 // -------------------------------------------------------------------------------- |
201 class klassItable; | 187 class klassItable; |
202 class itableMethodEntry; | 188 class itableMethodEntry; |
203 | 189 |
204 class itableOffsetEntry VALUE_OBJ_CLASS_SPEC { | 190 class itableOffsetEntry VALUE_OBJ_CLASS_SPEC { |
205 private: | 191 private: |
206 klassOop _interface; | 192 Klass* _interface; |
207 int _offset; | 193 int _offset; |
208 public: | 194 public: |
209 klassOop interface_klass() const { return _interface; } | 195 Klass* interface_klass() const { return _interface; } |
210 int offset() const { return _offset; } | 196 int offset() const { return _offset; } |
211 | 197 |
212 static itableMethodEntry* method_entry(klassOop k, int offset) { return (itableMethodEntry*)(((address)k) + offset); } | 198 static itableMethodEntry* method_entry(Klass* k, int offset) { return (itableMethodEntry*)(((address)k) + offset); } |
213 itableMethodEntry* first_method_entry(klassOop k) { return method_entry(k, _offset); } | 199 itableMethodEntry* first_method_entry(Klass* k) { return method_entry(k, _offset); } |
214 | 200 |
215 void initialize(klassOop interf, int offset) { _interface = interf; _offset = offset; } | 201 void initialize(Klass* interf, int offset) { _interface = interf; _offset = offset; } |
216 | 202 |
217 // Static size and offset accessors | 203 // Static size and offset accessors |
218 static int size() { return sizeof(itableOffsetEntry) / HeapWordSize; } // size in words | 204 static int size() { return sizeof(itableOffsetEntry) / HeapWordSize; } // size in words |
219 static int interface_offset_in_bytes() { return offset_of(itableOffsetEntry, _interface); } | 205 static int interface_offset_in_bytes() { return offset_of(itableOffsetEntry, _interface); } |
220 static int offset_offset_in_bytes() { return offset_of(itableOffsetEntry, _offset); } | 206 static int offset_offset_in_bytes() { return offset_of(itableOffsetEntry, _offset); } |
223 }; | 209 }; |
224 | 210 |
225 | 211 |
226 class itableMethodEntry VALUE_OBJ_CLASS_SPEC { | 212 class itableMethodEntry VALUE_OBJ_CLASS_SPEC { |
227 private: | 213 private: |
228 methodOop _method; | 214 Method* _method; |
229 | 215 |
230 public: | 216 public: |
231 methodOop method() const { return _method; } | 217 Method* method() const { return _method; } |
232 | 218 |
233 void clear() { _method = NULL; } | 219 void clear() { _method = NULL; } |
234 | 220 |
235 void initialize(methodOop method); | 221 void initialize(Method* method); |
236 | 222 |
237 // Static size and offset accessors | 223 // Static size and offset accessors |
238 static int size() { return sizeof(itableMethodEntry) / HeapWordSize; } // size in words | 224 static int size() { return sizeof(itableMethodEntry) / HeapWordSize; } // size in words |
239 static int method_offset_in_bytes() { return offset_of(itableMethodEntry, _method); } | 225 static int method_offset_in_bytes() { return offset_of(itableMethodEntry, _method); } |
240 | 226 |
243 | 229 |
244 // | 230 // |
245 // Format of an itable | 231 // Format of an itable |
246 // | 232 // |
247 // ---- offset table --- | 233 // ---- offset table --- |
248 // klassOop of interface 1 \ | 234 // Klass* of interface 1 \ |
249 // offset to vtable from start of oop / offset table entry | 235 // offset to vtable from start of oop / offset table entry |
250 // ... | 236 // ... |
251 // klassOop of interface n \ | 237 // Klass* of interface n \ |
252 // offset to vtable from start of oop / offset table entry | 238 // offset to vtable from start of oop / offset table entry |
253 // --- vtable for interface 1 --- | 239 // --- vtable for interface 1 --- |
254 // methodOop \ | 240 // Method* \ |
255 // compiler entry point / method table entry | 241 // compiler entry point / method table entry |
256 // ... | 242 // ... |
257 // methodOop \ | 243 // Method* \ |
258 // compiler entry point / method table entry | 244 // compiler entry point / method table entry |
259 // -- vtable for interface 2 --- | 245 // -- vtable for interface 2 --- |
260 // ... | 246 // ... |
261 // | 247 // |
262 class klassItable : public ResourceObj { | 248 class klassItable : public ResourceObj { |
280 | 266 |
281 // Initialization | 267 // Initialization |
282 void initialize_itable(bool checkconstraints, TRAPS); | 268 void initialize_itable(bool checkconstraints, TRAPS); |
283 | 269 |
284 // Updates | 270 // Updates |
285 void initialize_with_method(methodOop m); | 271 void initialize_with_method(Method* m); |
286 | 272 |
287 // RedefineClasses() API support: | 273 // RedefineClasses() API support: |
288 // if any entry of this itable points to any of old_methods, | 274 // if any entry of this itable points to any of old_methods, |
289 // replace it with the corresponding new_method. | 275 // replace it with the corresponding new_method. |
290 // trace_name_printed is set to true if the current call has | 276 // trace_name_printed is set to true if the current call has |
291 // printed the klass name so that other routines in the adjust_* | 277 // printed the klass name so that other routines in the adjust_* |
292 // group don't print the klass name. | 278 // group don't print the klass name. |
293 void adjust_method_entries(methodOop* old_methods, methodOop* new_methods, | 279 void adjust_method_entries(Method** old_methods, Method** new_methods, |
294 int methods_length, bool * trace_name_printed); | 280 int methods_length, bool * trace_name_printed); |
295 | 281 |
296 // Garbage collection | |
297 void oop_follow_contents(); | |
298 void oop_adjust_pointers(); | |
299 | |
300 #ifndef SERIALGC | |
301 // Parallel Old | |
302 void oop_follow_contents(ParCompactionManager* cm); | |
303 void oop_update_pointers(ParCompactionManager* cm); | |
304 #endif // SERIALGC | |
305 | |
306 // Iterators | |
307 void oop_oop_iterate(OopClosure* blk); | |
308 void oop_oop_iterate_m(OopClosure* blk, MemRegion mr); | |
309 | |
310 // Setup of itable | 282 // Setup of itable |
311 static int compute_itable_size(objArrayHandle transitive_interfaces); | 283 static int compute_itable_size(Array<Klass*>* transitive_interfaces); |
312 static void setup_itable_offset_table(instanceKlassHandle klass); | 284 static void setup_itable_offset_table(instanceKlassHandle klass); |
313 | 285 |
314 // Resolving of method to index | 286 // Resolving of method to index |
315 static int compute_itable_index(methodOop m); | 287 static int compute_itable_index(Method* m); |
316 // ...and back again: | 288 // ...and back again: |
317 static methodOop method_for_itable_index(klassOop klass, int itable_index); | 289 static Method* method_for_itable_index(Klass* klass, int itable_index); |
318 | 290 |
319 // Debugging/Statistics | 291 // Debugging/Statistics |
320 static void print_statistics() PRODUCT_RETURN; | 292 static void print_statistics() PRODUCT_RETURN; |
321 private: | 293 private: |
322 intptr_t* vtable_start() const { return ((intptr_t*)_klass()) + _table_offset; } | 294 intptr_t* vtable_start() const { return ((intptr_t*)_klass()) + _table_offset; } |
328 // Statistics | 300 // Statistics |
329 NOT_PRODUCT(static int _total_classes;) // Total no. of classes with itables | 301 NOT_PRODUCT(static int _total_classes;) // Total no. of classes with itables |
330 NOT_PRODUCT(static long _total_size;) // Total no. of bytes used for itables | 302 NOT_PRODUCT(static long _total_size;) // Total no. of bytes used for itables |
331 | 303 |
332 static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; }) | 304 static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; }) |
305 | |
306 public: | |
307 #ifndef PRODUCT | |
308 bool check_no_old_entries(); | |
309 #endif | |
333 }; | 310 }; |
334 | 311 |
335 #endif // SHARE_VM_OOPS_KLASSVTABLE_HPP | 312 #endif // SHARE_VM_OOPS_KLASSVTABLE_HPP |