Mercurial > hg > truffle
annotate src/share/vm/oops/klassVtable.hpp @ 452:00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery.
Reviewed-by: apetrusenko, jcoomes
author | ysr |
---|---|
date | Thu, 20 Nov 2008 12:27:41 -0800 |
parents | f8236e79048a |
children | 4aaa9f5e02a8 c89f86385056 |
rev | line source |
---|---|
0 | 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 | |
34 class vtableEntry; | |
35 | |
36 class 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 | |
145 class 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 | |
165 inline 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 | |
172 inline 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 | |
177 inline 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 // -------------------------------------------------------------------------------- | |
184 class klassItable; | |
185 class itableMethodEntry; | |
186 | |
187 class 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 | |
209 class 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 // | |
245 class 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 | |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
262 int size_offset_table() { return _size_offset_table; } |
0 | 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 }; |