Thu, 07 Apr 2011 09:53:20 -0700
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes
1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #ifndef SHARE_VM_OOPS_KLASSVTABLE_HPP
26 #define SHARE_VM_OOPS_KLASSVTABLE_HPP
28 #include "memory/allocation.hpp"
29 #include "oops/oopsHierarchy.hpp"
30 #include "runtime/handles.hpp"
31 #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,
35 // not to actually hold the vtable data.
36 // Note: the klassVtable should not be accessed before the class has been verified
37 // (until that point, the vtable is uninitialized).
39 // Currently a klassVtable contains a direct reference to the vtable data, and is therefore
40 // not preserved across GCs.
42 class vtableEntry;
44 class klassVtable : public ResourceObj {
45 KlassHandle _klass; // my klass
46 int _tableOffset; // offset of start of vtable data within klass
47 int _length; // length of vtable (number of entries)
48 #ifndef PRODUCT
49 int _verify_count; // to make verify faster
50 #endif
52 // Ordering important, so greater_than (>) can be used as an merge operator.
53 enum AccessType {
54 acc_private = 0,
55 acc_package_private = 1,
56 acc_publicprotected = 2
57 };
59 public:
60 klassVtable(KlassHandle h_klass, void* base, int length) : _klass(h_klass) {
61 _tableOffset = (address)base - (address)h_klass(); _length = length;
62 }
64 // accessors
65 vtableEntry* table() const { return (vtableEntry*)(address(_klass()) + _tableOffset); }
66 KlassHandle klass() const { return _klass; }
67 int length() const { return _length; }
68 inline methodOop method_at(int i) const;
69 inline methodOop unchecked_method_at(int i) const;
70 inline oop* adr_method_at(int i) const;
72 // searching; all methods return -1 if not found
73 int index_of(methodOop m) const { return index_of(m, _length); }
74 int index_of_miranda(Symbol* name, Symbol* signature);
76 void initialize_vtable(bool checkconstraints, TRAPS); // initialize vtable of a new klass
78 // conputes vtable length (in words) and the number of miranda methods
79 static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods,
80 klassOop super, objArrayOop methods,
81 AccessFlags class_flags, Handle classloader,
82 Symbol* classname, objArrayOop local_interfaces,
83 TRAPS);
85 // RedefineClasses() API support:
86 // If any entry of this vtable points to any of old_methods,
87 // replace it with the corresponding new_method.
88 // trace_name_printed is set to true if the current call has
89 // printed the klass name so that other routines in the adjust_*
90 // group don't print the klass name.
91 void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
92 int methods_length, bool * trace_name_printed);
94 // Garbage collection
95 void oop_follow_contents();
96 void oop_adjust_pointers();
98 #ifndef SERIALGC
99 // Parallel Old
100 void oop_follow_contents(ParCompactionManager* cm);
101 void oop_update_pointers(ParCompactionManager* cm);
102 #endif // SERIALGC
104 // Iterators
105 void oop_oop_iterate(OopClosure* blk);
106 void oop_oop_iterate_m(OopClosure* blk, MemRegion mr);
108 // Debugging code
109 void print() PRODUCT_RETURN;
110 void verify(outputStream* st, bool force = false);
111 static void print_statistics() PRODUCT_RETURN;
113 #ifndef PRODUCT
114 bool check_no_old_entries();
115 void dump_vtable();
116 #endif
118 protected:
119 friend class vtableEntry;
120 private:
121 enum { VTABLE_TRANSITIVE_OVERRIDE_VERSION = 51 } ;
122 void copy_vtable_to(vtableEntry* start);
123 int initialize_from_super(KlassHandle super);
124 int index_of(methodOop m, int len) const; // same as index_of, but search only up to len
125 void put_method_at(methodOop m, int index);
126 static bool needs_new_vtable_entry(methodHandle m, klassOop super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS);
128 bool update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS);
129 instanceKlass* find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, int vtable_index,
130 Handle target_loader, Symbol* target_classname, Thread* THREAD);
132 // support for miranda methods
133 bool is_miranda_entry_at(int i);
134 void fill_in_mirandas(int& initialized);
135 static bool is_miranda(methodOop m, objArrayOop class_methods, klassOop super);
136 static void add_new_mirandas_to_list(GrowableArray<methodOop>* list_of_current_mirandas, objArrayOop current_interface_methods, objArrayOop class_methods, klassOop super);
137 static void get_mirandas(GrowableArray<methodOop>* mirandas, klassOop super, objArrayOop class_methods, objArrayOop local_interfaces);
138 static int get_num_mirandas(klassOop super, objArrayOop class_methods, objArrayOop local_interfaces);
141 void verify_against(outputStream* st, klassVtable* vt, int index);
142 inline instanceKlass* ik() const;
143 };
146 // private helper class for klassVtable
147 // description of entry points:
148 // destination is interpreted:
149 // from_compiled_code_entry_point -> c2iadapter
150 // from_interpreter_entry_point -> interpreter entry point
151 // destination is compiled:
152 // from_compiled_code_entry_point -> nmethod entry point
153 // from_interpreter_entry_point -> i2cadapter
154 class vtableEntry VALUE_OBJ_CLASS_SPEC {
155 public:
156 // size in words
157 static int size() {
158 return sizeof(vtableEntry) / sizeof(HeapWord);
159 }
160 static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); }
161 methodOop method() const { return _method; }
163 private:
164 methodOop _method;
165 void set(methodOop method) { assert(method != NULL, "use clear"); _method = method; }
166 void clear() { _method = NULL; }
167 void print() PRODUCT_RETURN;
168 void verify(klassVtable* vt, outputStream* st);
170 friend class klassVtable;
171 };
174 inline methodOop klassVtable::method_at(int i) const {
175 assert(i >= 0 && i < _length, "index out of bounds");
176 assert(table()[i].method() != NULL, "should not be null");
177 assert(oop(table()[i].method())->is_method(), "should be method");
178 return table()[i].method();
179 }
181 inline methodOop klassVtable::unchecked_method_at(int i) const {
182 assert(i >= 0 && i < _length, "index out of bounds");
183 return table()[i].method();
184 }
186 inline oop* klassVtable::adr_method_at(int i) const {
187 // Allow one past the last entry to be referenced; useful for loop bounds.
188 assert(i >= 0 && i <= _length, "index out of bounds");
189 return (oop*)(address(table() + i) + vtableEntry::method_offset_in_bytes());
190 }
192 // --------------------------------------------------------------------------------
193 class klassItable;
194 class itableMethodEntry;
196 class itableOffsetEntry VALUE_OBJ_CLASS_SPEC {
197 private:
198 klassOop _interface;
199 int _offset;
200 public:
201 klassOop interface_klass() const { return _interface; }
202 int offset() const { return _offset; }
204 static itableMethodEntry* method_entry(klassOop k, int offset) { return (itableMethodEntry*)(((address)k) + offset); }
205 itableMethodEntry* first_method_entry(klassOop k) { return method_entry(k, _offset); }
207 void initialize(klassOop interf, int offset) { _interface = interf; _offset = offset; }
209 // Static size and offset accessors
210 static int size() { return sizeof(itableOffsetEntry) / HeapWordSize; } // size in words
211 static int interface_offset_in_bytes() { return offset_of(itableOffsetEntry, _interface); }
212 static int offset_offset_in_bytes() { return offset_of(itableOffsetEntry, _offset); }
214 friend class klassItable;
215 };
218 class itableMethodEntry VALUE_OBJ_CLASS_SPEC {
219 private:
220 methodOop _method;
222 public:
223 methodOop method() const { return _method; }
225 void clear() { _method = NULL; }
227 void initialize(methodOop method);
229 // Static size and offset accessors
230 static int size() { return sizeof(itableMethodEntry) / HeapWordSize; } // size in words
231 static int method_offset_in_bytes() { return offset_of(itableMethodEntry, _method); }
233 friend class klassItable;
234 };
236 //
237 // Format of an itable
238 //
239 // ---- offset table ---
240 // klassOop of interface 1 \
241 // offset to vtable from start of oop / offset table entry
242 // ...
243 // klassOop of interface n \
244 // offset to vtable from start of oop / offset table entry
245 // --- vtable for interface 1 ---
246 // methodOop \
247 // compiler entry point / method table entry
248 // ...
249 // methodOop \
250 // compiler entry point / method table entry
251 // -- vtable for interface 2 ---
252 // ...
253 //
254 class klassItable : public ResourceObj {
255 private:
256 instanceKlassHandle _klass; // my klass
257 int _table_offset; // offset of start of itable data within klass (in words)
258 int _size_offset_table; // size of offset table (in itableOffset entries)
259 int _size_method_table; // size of methodtable (in itableMethodEntry entries)
261 void initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS);
262 public:
263 klassItable(instanceKlassHandle klass);
265 itableOffsetEntry* offset_entry(int i) { assert(0 <= i && i <= _size_offset_table, "index out of bounds");
266 return &((itableOffsetEntry*)vtable_start())[i]; }
268 itableMethodEntry* method_entry(int i) { assert(0 <= i && i <= _size_method_table, "index out of bounds");
269 return &((itableMethodEntry*)method_start())[i]; }
271 int size_offset_table() { return _size_offset_table; }
273 // Initialization
274 void initialize_itable(bool checkconstraints, TRAPS);
276 // Updates
277 void initialize_with_method(methodOop m);
279 // RedefineClasses() API support:
280 // if any entry of this itable points to any of old_methods,
281 // replace it with the corresponding new_method.
282 // trace_name_printed is set to true if the current call has
283 // printed the klass name so that other routines in the adjust_*
284 // group don't print the klass name.
285 void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
286 int methods_length, bool * trace_name_printed);
288 // Garbage collection
289 void oop_follow_contents();
290 void oop_adjust_pointers();
292 #ifndef SERIALGC
293 // Parallel Old
294 void oop_follow_contents(ParCompactionManager* cm);
295 void oop_update_pointers(ParCompactionManager* cm);
296 #endif // SERIALGC
298 // Iterators
299 void oop_oop_iterate(OopClosure* blk);
300 void oop_oop_iterate_m(OopClosure* blk, MemRegion mr);
302 // Setup of itable
303 static int compute_itable_size(objArrayHandle transitive_interfaces);
304 static void setup_itable_offset_table(instanceKlassHandle klass);
306 // Resolving of method to index
307 static int compute_itable_index(methodOop m);
308 // ...and back again:
309 static methodOop method_for_itable_index(klassOop klass, int itable_index);
311 // Debugging/Statistics
312 static void print_statistics() PRODUCT_RETURN;
313 private:
314 intptr_t* vtable_start() const { return ((intptr_t*)_klass()) + _table_offset; }
315 intptr_t* method_start() const { return vtable_start() + _size_offset_table * itableOffsetEntry::size(); }
317 // Helper methods
318 static int calc_itable_size(int num_interfaces, int num_methods) { return (num_interfaces * itableOffsetEntry::size()) + (num_methods * itableMethodEntry::size()); }
320 // Statistics
321 NOT_PRODUCT(static int _total_classes;) // Total no. of classes with itables
322 NOT_PRODUCT(static long _total_size;) // Total no. of bytes used for itables
324 static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
325 };
327 #endif // SHARE_VM_OOPS_KLASSVTABLE_HPP