Mercurial > hg > truffle
annotate src/share/vm/oops/klassVtable.cpp @ 4710:41406797186b
7113012: G1: rename not-fully-young GCs as "mixed"
Summary: Renamed partially-young GCs as mixed and fully-young GCs as young. Change all external output that includes those terms (GC log and GC ergo log) as well as any comments, fields, methods, etc. The changeset also includes very minor code tidying up (added some curly brackets).
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Fri, 16 Dec 2011 02:14:27 -0500 |
parents | 8ce625481709 |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
2227 | 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "classfile/vmSymbols.hpp" | |
28 #include "gc_implementation/shared/markSweep.inline.hpp" | |
29 #include "memory/gcLocker.hpp" | |
30 #include "memory/resourceArea.hpp" | |
31 #include "memory/universe.inline.hpp" | |
32 #include "oops/instanceKlass.hpp" | |
33 #include "oops/klassOop.hpp" | |
34 #include "oops/klassVtable.hpp" | |
35 #include "oops/methodOop.hpp" | |
36 #include "oops/objArrayOop.hpp" | |
37 #include "oops/oop.inline.hpp" | |
38 #include "prims/jvmtiRedefineClassesTrace.hpp" | |
39 #include "runtime/arguments.hpp" | |
40 #include "runtime/handles.inline.hpp" | |
41 #include "utilities/copy.hpp" | |
0 | 42 |
43 inline instanceKlass* klassVtable::ik() const { | |
44 Klass* k = _klass()->klass_part(); | |
45 assert(k->oop_is_instance(), "not an instanceKlass"); | |
46 return (instanceKlass*)k; | |
47 } | |
48 | |
49 | |
50 // this function computes the vtable size (including the size needed for miranda | |
51 // methods) and the number of miranda methods in this class | |
52 // Note on Miranda methods: Let's say there is a class C that implements | |
53 // interface I. Let's say there is a method m in I that neither C nor any | |
54 // of its super classes implement (i.e there is no method of any access, with | |
55 // the same name and signature as m), then m is a Miranda method which is | |
56 // entered as a public abstract method in C's vtable. From then on it should | |
57 // treated as any other public method in C for method over-ride purposes. | |
58 void klassVtable::compute_vtable_size_and_num_mirandas(int &vtable_length, | |
59 int &num_miranda_methods, | |
60 klassOop super, | |
61 objArrayOop methods, | |
62 AccessFlags class_flags, | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
63 Handle classloader, |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
64 Symbol* classname, |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
65 objArrayOop local_interfaces, |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
66 TRAPS |
0 | 67 ) { |
68 | |
69 No_Safepoint_Verifier nsv; | |
70 | |
71 // set up default result values | |
72 vtable_length = 0; | |
73 num_miranda_methods = 0; | |
74 | |
75 // start off with super's vtable length | |
76 instanceKlass* sk = (instanceKlass*)super->klass_part(); | |
77 vtable_length = super == NULL ? 0 : sk->vtable_length(); | |
78 | |
79 // go thru each method in the methods table to see if it needs a new entry | |
80 int len = methods->length(); | |
81 for (int i = 0; i < len; i++) { | |
82 assert(methods->obj_at(i)->is_method(), "must be a methodOop"); | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
83 methodHandle mh(THREAD, methodOop(methods->obj_at(i))); |
0 | 84 |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
85 if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) { |
0 | 86 vtable_length += vtableEntry::size(); // we need a new entry |
87 } | |
88 } | |
89 | |
90 // compute the number of mirandas methods that must be added to the end | |
91 num_miranda_methods = get_num_mirandas(super, methods, local_interfaces); | |
92 vtable_length += (num_miranda_methods * vtableEntry::size()); | |
93 | |
94 if (Universe::is_bootstrapping() && vtable_length == 0) { | |
95 // array classes don't have their superclass set correctly during | |
96 // bootstrapping | |
97 vtable_length = Universe::base_vtable_size(); | |
98 } | |
99 | |
100 if (super == NULL && !Universe::is_bootstrapping() && | |
101 vtable_length != Universe::base_vtable_size()) { | |
102 // Someone is attempting to redefine java.lang.Object incorrectly. The | |
103 // only way this should happen is from | |
104 // SystemDictionary::resolve_from_stream(), which will detect this later | |
105 // and throw a security exception. So don't assert here to let | |
106 // the exception occur. | |
107 vtable_length = Universe::base_vtable_size(); | |
108 } | |
109 assert(super != NULL || vtable_length == Universe::base_vtable_size(), | |
110 "bad vtable size for class Object"); | |
111 assert(vtable_length % vtableEntry::size() == 0, "bad vtable length"); | |
112 assert(vtable_length >= Universe::base_vtable_size(), "vtable too small"); | |
113 } | |
114 | |
115 int klassVtable::index_of(methodOop m, int len) const { | |
116 assert(m->vtable_index() >= 0, "do not ask this of non-vtable methods"); | |
117 return m->vtable_index(); | |
118 } | |
119 | |
120 int klassVtable::initialize_from_super(KlassHandle super) { | |
121 if (super.is_null()) { | |
122 return 0; | |
123 } else { | |
124 // copy methods from superKlass | |
125 // can't inherit from array class, so must be instanceKlass | |
126 assert(super->oop_is_instance(), "must be instance klass"); | |
127 instanceKlass* sk = (instanceKlass*)super()->klass_part(); | |
128 klassVtable* superVtable = sk->vtable(); | |
129 assert(superVtable->length() <= _length, "vtable too short"); | |
130 #ifdef ASSERT | |
131 superVtable->verify(tty, true); | |
132 #endif | |
133 superVtable->copy_vtable_to(table()); | |
134 #ifndef PRODUCT | |
135 if (PrintVtables && Verbose) { | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
136 ResourceMark rm; |
0 | 137 tty->print_cr("copy vtable from %s to %s size %d", sk->internal_name(), klass()->internal_name(), _length); |
138 } | |
139 #endif | |
140 return superVtable->length(); | |
141 } | |
142 } | |
143 | |
144 // Revised lookup semantics introduced 1.3 (Kestral beta) | |
145 void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { | |
146 | |
147 // Note: Arrays can have intermediate array supers. Use java_super to skip them. | |
148 KlassHandle super (THREAD, klass()->java_super()); | |
149 int nofNewEntries = 0; | |
150 | |
151 | |
152 if (PrintVtables && !klass()->oop_is_array()) { | |
153 ResourceMark rm(THREAD); | |
154 tty->print_cr("Initializing: %s", _klass->name()->as_C_string()); | |
155 } | |
156 | |
157 #ifdef ASSERT | |
158 oop* end_of_obj = (oop*)_klass() + _klass()->size(); | |
159 oop* end_of_vtable = (oop*)&table()[_length]; | |
160 assert(end_of_vtable <= end_of_obj, "vtable extends beyond end"); | |
161 #endif | |
162 | |
163 if (Universe::is_bootstrapping()) { | |
164 // just clear everything | |
165 for (int i = 0; i < _length; i++) table()[i].clear(); | |
166 return; | |
167 } | |
168 | |
169 int super_vtable_len = initialize_from_super(super); | |
170 if (klass()->oop_is_array()) { | |
171 assert(super_vtable_len == _length, "arrays shouldn't introduce new methods"); | |
172 } else { | |
173 assert(_klass->oop_is_instance(), "must be instanceKlass"); | |
174 | |
175 objArrayHandle methods(THREAD, ik()->methods()); | |
176 int len = methods()->length(); | |
177 int initialized = super_vtable_len; | |
178 | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
179 // update_inherited_vtable can stop for gc - ensure using handles |
0 | 180 for (int i = 0; i < len; i++) { |
181 HandleMark hm(THREAD); | |
182 assert(methods()->obj_at(i)->is_method(), "must be a methodOop"); | |
183 methodHandle mh(THREAD, (methodOop)methods()->obj_at(i)); | |
184 | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
185 bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK); |
0 | 186 |
187 if (needs_new_entry) { | |
188 put_method_at(mh(), initialized); | |
189 mh()->set_vtable_index(initialized); // set primary vtable index | |
190 initialized++; | |
191 } | |
192 } | |
193 | |
194 // add miranda methods; it will also update the value of initialized | |
195 fill_in_mirandas(initialized); | |
196 | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
197 // In class hierarchies where the accessibility is not increasing (i.e., going from private -> |
0 | 198 // package_private -> publicprotected), the vtable might actually be smaller than our initial |
199 // calculation. | |
200 assert(initialized <= _length, "vtable initialization failed"); | |
201 for(;initialized < _length; initialized++) { | |
202 put_method_at(NULL, initialized); | |
203 } | |
204 NOT_PRODUCT(verify(tty, true)); | |
205 } | |
206 } | |
207 | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
208 // Called for cases where a method does not override its superclass' vtable entry |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
209 // For bytecodes not produced by javac together it is possible that a method does not override |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
210 // the superclass's method, but might indirectly override a super-super class's vtable entry |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
211 // If none found, return a null superk, else return the superk of the method this does override |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
212 instanceKlass* klassVtable::find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
213 int vtable_index, Handle target_loader, Symbol* target_classname, Thread * THREAD) { |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
214 instanceKlass* superk = initialsuper; |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
215 while (superk != NULL && superk->super() != NULL) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
216 instanceKlass* supersuperklass = instanceKlass::cast(superk->super()); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
217 klassVtable* ssVtable = supersuperklass->vtable(); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
218 if (vtable_index < ssVtable->length()) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
219 methodOop super_method = ssVtable->method_at(vtable_index); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
220 #ifndef PRODUCT |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
221 Symbol* name= target_method()->name(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
222 Symbol* signature = target_method()->signature(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
223 assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch"); |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
224 #endif |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
225 if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
226 #ifndef PRODUCT |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
227 if (PrintVtables && Verbose) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
228 ResourceMark rm(THREAD); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
229 tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ", |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
230 supersuperklass->internal_name(), |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
231 _klass->internal_name(), (target_method() != NULL) ? |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
232 target_method()->name()->as_C_string() : "<NULL>", vtable_index); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
233 super_method->access_flags().print_on(tty); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
234 tty->print("overriders flags: "); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
235 target_method->access_flags().print_on(tty); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
236 tty->cr(); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
237 } |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
238 #endif /*PRODUCT*/ |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
239 break; // return found superk |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
240 } |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
241 } else { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
242 // super class has no vtable entry here, stop transitive search |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
243 superk = (instanceKlass*)NULL; |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
244 break; |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
245 } |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
246 // if no override found yet, continue to search up |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
247 superk = instanceKlass::cast(superk->super()); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
248 } |
0 | 249 |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
250 return superk; |
0 | 251 } |
252 | |
253 | |
254 // Update child's copy of super vtable for overrides | |
255 // OR return true if a new vtable entry is required | |
256 // Only called for instanceKlass's, i.e. not for arrays | |
257 // If that changed, could not use _klass as handle for klass | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
258 bool klassVtable::update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
259 bool checkconstraints, TRAPS) { |
0 | 260 ResourceMark rm; |
261 bool allocate_new = true; | |
262 assert(klass->oop_is_instance(), "must be instanceKlass"); | |
263 | |
264 // Initialize the method's vtable index to "nonvirtual". | |
265 // If we allocate a vtable entry, we will update it to a non-negative number. | |
266 target_method()->set_vtable_index(methodOopDesc::nonvirtual_vtable_index); | |
267 | |
268 // Static and <init> methods are never in | |
269 if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) { | |
270 return false; | |
271 } | |
272 | |
273 if (klass->is_final() || target_method()->is_final()) { | |
274 // a final method never needs a new entry; final methods can be statically | |
275 // resolved and they have to be present in the vtable only if they override | |
276 // a super's method, in which case they re-use its entry | |
277 allocate_new = false; | |
278 } | |
279 | |
280 // we need a new entry if there is no superclass | |
281 if (klass->super() == NULL) { | |
282 return allocate_new; | |
283 } | |
284 | |
285 // private methods always have a new entry in the vtable | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
286 // specification interpretation since classic has |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
287 // private methods not overriding |
0 | 288 if (target_method()->is_private()) { |
289 return allocate_new; | |
290 } | |
291 | |
292 // search through the vtable and update overridden entries | |
293 // Since check_signature_loaders acquires SystemDictionary_lock | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
294 // which can block for gc, once we are in this loop, use handles |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
295 // For classfiles built with >= jdk7, we now look for transitive overrides |
0 | 296 |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
297 Symbol* name = target_method()->name(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
298 Symbol* signature = target_method()->signature(); |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
299 Handle target_loader(THREAD, _klass->class_loader()); |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
300 Symbol* target_classname = _klass->name(); |
0 | 301 for(int i = 0; i < super_vtable_len; i++) { |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
302 methodOop super_method = method_at(i); |
0 | 303 // Check if method name matches |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
304 if (super_method->name() == name && super_method->signature() == signature) { |
0 | 305 |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
306 // get super_klass for method_holder for the found method |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
307 instanceKlass* super_klass = instanceKlass::cast(super_method->method_holder()); |
0 | 308 |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
309 if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) || |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
310 ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION) |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
311 && ((super_klass = find_transitive_override(super_klass, target_method, i, target_loader, |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
312 target_classname, THREAD)) != (instanceKlass*)NULL))) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
313 // overriding, so no new entry |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
314 allocate_new = false; |
0 | 315 |
316 if (checkconstraints) { | |
317 // Override vtable entry if passes loader constraint check | |
318 // if loader constraint checking requested | |
319 // No need to visit his super, since he and his super | |
320 // have already made any needed loader constraints. | |
321 // Since loader constraints are transitive, it is enough | |
322 // to link to the first super, and we get all the others. | |
323 Handle super_loader(THREAD, super_klass->class_loader()); | |
324 | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
325 if (target_loader() != super_loader()) { |
0 | 326 ResourceMark rm(THREAD); |
327 char* failed_type_name = | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
328 SystemDictionary::check_signature_loaders(signature, target_loader, |
0 | 329 super_loader, true, |
330 CHECK_(false)); | |
331 if (failed_type_name != NULL) { | |
332 const char* msg = "loader constraint violation: when resolving " | |
333 "overridden method \"%s\" the class loader (instance" | |
334 " of %s) of the current class, %s, and its superclass loader " | |
335 "(instance of %s), have different Class objects for the type " | |
336 "%s used in the signature"; | |
337 char* sig = target_method()->name_and_sig_as_C_string(); | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
338 const char* loader1 = SystemDictionary::loader_name(target_loader()); |
0 | 339 char* current = _klass->name()->as_C_string(); |
340 const char* loader2 = SystemDictionary::loader_name(super_loader()); | |
341 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + | |
342 strlen(current) + strlen(loader2) + strlen(failed_type_name); | |
343 char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); | |
344 jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2, | |
345 failed_type_name); | |
346 THROW_MSG_(vmSymbols::java_lang_LinkageError(), buf, false); | |
347 } | |
348 } | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
349 } |
0 | 350 |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
351 put_method_at(target_method(), i); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
352 target_method()->set_vtable_index(i); |
0 | 353 #ifndef PRODUCT |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
354 if (PrintVtables && Verbose) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
355 tty->print("overriding with %s::%s index %d, original flags: ", |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
356 _klass->internal_name(), (target_method() != NULL) ? |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
357 target_method()->name()->as_C_string() : "<NULL>", i); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
358 super_method->access_flags().print_on(tty); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
359 tty->print("overriders flags: "); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
360 target_method->access_flags().print_on(tty); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
361 tty->cr(); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
362 } |
0 | 363 #endif /*PRODUCT*/ |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
364 } else { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
365 // allocate_new = true; default. We might override one entry, |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
366 // but not override another. Once we override one, not need new |
0 | 367 #ifndef PRODUCT |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
368 if (PrintVtables && Verbose) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
369 tty->print("NOT overriding with %s::%s index %d, original flags: ", |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
370 _klass->internal_name(), (target_method() != NULL) ? |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
371 target_method()->name()->as_C_string() : "<NULL>", i); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
372 super_method->access_flags().print_on(tty); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
373 tty->print("overriders flags: "); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
374 target_method->access_flags().print_on(tty); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
375 tty->cr(); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
376 } |
0 | 377 #endif /*PRODUCT*/ |
378 } | |
379 } | |
380 } | |
381 return allocate_new; | |
382 } | |
383 | |
384 void klassVtable::put_method_at(methodOop m, int index) { | |
385 assert(m->is_oop_or_null(), "Not an oop or null"); | |
386 #ifndef PRODUCT | |
387 if (PrintVtables && Verbose) { | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
388 ResourceMark rm; |
0 | 389 tty->print_cr("adding %s::%s at index %d", _klass->internal_name(), |
390 (m != NULL) ? m->name()->as_C_string() : "<NULL>", index); | |
391 } | |
392 assert(unchecked_method_at(index)->is_oop_or_null(), "Not an oop or null"); | |
393 #endif | |
394 table()[index].set(m); | |
395 } | |
396 | |
397 // Find out if a method "m" with superclass "super", loader "classloader" and | |
398 // name "classname" needs a new vtable entry. Let P be a class package defined | |
399 // by "classloader" and "classname". | |
400 // NOTE: The logic used here is very similar to the one used for computing | |
401 // the vtables indices for a method. We cannot directly use that function because, | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
402 // we allocate the instanceKlass at load time, and that requires that the |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
403 // superclass has been loaded. |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
404 // However, the vtable entries are filled in at link time, and therefore |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
405 // the superclass' vtable may not yet have been filled in. |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
406 bool klassVtable::needs_new_vtable_entry(methodHandle target_method, |
0 | 407 klassOop super, |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
408 Handle classloader, |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
409 Symbol* classname, |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
410 AccessFlags class_flags, |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
411 TRAPS) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
412 if ((class_flags.is_final() || target_method()->is_final()) || |
0 | 413 // a final method never needs a new entry; final methods can be statically |
414 // resolved and they have to be present in the vtable only if they override | |
415 // a super's method, in which case they re-use its entry | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
416 (target_method()->is_static()) || |
0 | 417 // static methods don't need to be in vtable |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
418 (target_method()->name() == vmSymbols::object_initializer_name()) |
0 | 419 // <init> is never called dynamically-bound |
420 ) { | |
421 return false; | |
422 } | |
423 | |
424 // we need a new entry if there is no superclass | |
425 if (super == NULL) { | |
426 return true; | |
427 } | |
428 | |
429 // private methods always have a new entry in the vtable | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
430 // specification interpretation since classic has |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
431 // private methods not overriding |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
432 if (target_method()->is_private()) { |
0 | 433 return true; |
434 } | |
435 | |
436 // search through the super class hierarchy to see if we need | |
437 // a new entry | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
438 ResourceMark rm; |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
439 Symbol* name = target_method()->name(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
440 Symbol* signature = target_method()->signature(); |
0 | 441 klassOop k = super; |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
442 methodOop super_method = NULL; |
0 | 443 instanceKlass *holder = NULL; |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
444 methodOop recheck_method = NULL; |
0 | 445 while (k != NULL) { |
446 // lookup through the hierarchy for a method with matching name and sign. | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
447 super_method = instanceKlass::cast(k)->lookup_method(name, signature); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
448 if (super_method == NULL) { |
0 | 449 break; // we still have to search for a matching miranda method |
450 } | |
451 // get the class holding the matching method | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
452 // make sure you use that class for is_override |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
453 instanceKlass* superk = instanceKlass::cast(super_method->method_holder()); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
454 // we want only instance method matches |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
455 // pretend private methods are not in the super vtable |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
456 // since we do override around them: e.g. a.m pub/b.m private/c.m pub, |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
457 // ignore private, c.m pub does override a.m pub |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
458 // For classes that were not javac'd together, we also do transitive overriding around |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
459 // methods that have less accessibility |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
460 if ((!super_method->is_static()) && |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
461 (!super_method->is_private())) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
462 if (superk->is_override(super_method, classloader, classname, THREAD)) { |
0 | 463 return false; |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
464 // else keep looking for transitive overrides |
0 | 465 } |
466 } | |
467 | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
468 // Start with lookup result and continue to search up |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
469 k = superk->super(); // haven't found an override match yet; continue to look |
0 | 470 } |
471 | |
472 // if the target method is public or protected it may have a matching | |
473 // miranda method in the super, whose entry it should re-use. | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
474 // Actually, to handle cases that javac would not generate, we need |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
475 // this check for all access permissions. |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
476 instanceKlass *sk = instanceKlass::cast(super); |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
477 if (sk->has_miranda_methods()) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
478 if (sk->lookup_method_in_all_interfaces(name, signature) != NULL) { |
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
479 return false; // found a matching miranda; we do not need a new entry |
0 | 480 } |
481 } | |
482 return true; // found no match; we need a new entry | |
483 } | |
484 | |
485 // Support for miranda methods | |
486 | |
487 // get the vtable index of a miranda method with matching "name" and "signature" | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
488 int klassVtable::index_of_miranda(Symbol* name, Symbol* signature) { |
0 | 489 // search from the bottom, might be faster |
490 for (int i = (length() - 1); i >= 0; i--) { | |
491 methodOop m = table()[i].method(); | |
492 if (is_miranda_entry_at(i) && | |
493 m->name() == name && m->signature() == signature) { | |
494 return i; | |
495 } | |
496 } | |
497 return methodOopDesc::invalid_vtable_index; | |
498 } | |
499 | |
500 // check if an entry is miranda | |
501 bool klassVtable::is_miranda_entry_at(int i) { | |
502 methodOop m = method_at(i); | |
503 klassOop method_holder = m->method_holder(); | |
504 instanceKlass *mhk = instanceKlass::cast(method_holder); | |
505 | |
506 // miranda methods are interface methods in a class's vtable | |
507 if (mhk->is_interface()) { | |
508 assert(m->is_public() && m->is_abstract(), "should be public and abstract"); | |
509 assert(ik()->implements_interface(method_holder) , "this class should implement the interface"); | |
510 assert(is_miranda(m, ik()->methods(), ik()->super()), "should be a miranda_method"); | |
511 return true; | |
512 } | |
513 return false; | |
514 } | |
515 | |
516 // check if a method is a miranda method, given a class's methods table and it's super | |
517 // the caller must make sure that the method belongs to an interface implemented by the class | |
518 bool klassVtable::is_miranda(methodOop m, objArrayOop class_methods, klassOop super) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
519 Symbol* name = m->name(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
520 Symbol* signature = m->signature(); |
0 | 521 if (instanceKlass::find_method(class_methods, name, signature) == NULL) { |
2018
642e54d1850a
6989076: JVM crashes in klassItable::initialize_itable_for_interface
dsamersoff
parents:
1972
diff
changeset
|
522 // did not find it in the method table of the current class |
0 | 523 if (super == NULL) { |
524 // super doesn't exist | |
525 return true; | |
2018
642e54d1850a
6989076: JVM crashes in klassItable::initialize_itable_for_interface
dsamersoff
parents:
1972
diff
changeset
|
526 } |
642e54d1850a
6989076: JVM crashes in klassItable::initialize_itable_for_interface
dsamersoff
parents:
1972
diff
changeset
|
527 |
642e54d1850a
6989076: JVM crashes in klassItable::initialize_itable_for_interface
dsamersoff
parents:
1972
diff
changeset
|
528 methodOop mo = instanceKlass::cast(super)->lookup_method(name, signature); |
642e54d1850a
6989076: JVM crashes in klassItable::initialize_itable_for_interface
dsamersoff
parents:
1972
diff
changeset
|
529 if (mo == NULL || mo->access_flags().is_private() ) { |
642e54d1850a
6989076: JVM crashes in klassItable::initialize_itable_for_interface
dsamersoff
parents:
1972
diff
changeset
|
530 // super class hierarchy does not implement it or protection is different |
642e54d1850a
6989076: JVM crashes in klassItable::initialize_itable_for_interface
dsamersoff
parents:
1972
diff
changeset
|
531 return true; |
0 | 532 } |
533 } | |
2018
642e54d1850a
6989076: JVM crashes in klassItable::initialize_itable_for_interface
dsamersoff
parents:
1972
diff
changeset
|
534 |
0 | 535 return false; |
536 } | |
537 | |
538 void klassVtable::add_new_mirandas_to_list(GrowableArray<methodOop>* list_of_current_mirandas, | |
539 objArrayOop current_interface_methods, | |
540 objArrayOop class_methods, | |
541 klassOop super) { | |
542 // iterate thru the current interface's method to see if it a miranda | |
543 int num_methods = current_interface_methods->length(); | |
544 for (int i = 0; i < num_methods; i++) { | |
545 methodOop im = methodOop(current_interface_methods->obj_at(i)); | |
546 bool is_duplicate = false; | |
547 int num_of_current_mirandas = list_of_current_mirandas->length(); | |
548 // check for duplicate mirandas in different interfaces we implement | |
549 for (int j = 0; j < num_of_current_mirandas; j++) { | |
550 methodOop miranda = list_of_current_mirandas->at(j); | |
551 if ((im->name() == miranda->name()) && | |
552 (im->signature() == miranda->signature())) { | |
553 is_duplicate = true; | |
554 break; | |
555 } | |
556 } | |
557 | |
558 if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable | |
559 if (is_miranda(im, class_methods, super)) { // is it a miranda at all? | |
560 instanceKlass *sk = instanceKlass::cast(super); | |
561 // check if it is a duplicate of a super's miranda | |
562 if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) { | |
563 list_of_current_mirandas->append(im); | |
564 } | |
565 } | |
566 } | |
567 } | |
568 } | |
569 | |
570 void klassVtable::get_mirandas(GrowableArray<methodOop>* mirandas, | |
571 klassOop super, objArrayOop class_methods, | |
572 objArrayOop local_interfaces) { | |
573 assert((mirandas->length() == 0) , "current mirandas must be 0"); | |
574 | |
575 // iterate thru the local interfaces looking for a miranda | |
576 int num_local_ifs = local_interfaces->length(); | |
577 for (int i = 0; i < num_local_ifs; i++) { | |
578 instanceKlass *ik = instanceKlass::cast(klassOop(local_interfaces->obj_at(i))); | |
579 add_new_mirandas_to_list(mirandas, ik->methods(), class_methods, super); | |
580 // iterate thru each local's super interfaces | |
581 objArrayOop super_ifs = ik->transitive_interfaces(); | |
582 int num_super_ifs = super_ifs->length(); | |
583 for (int j = 0; j < num_super_ifs; j++) { | |
584 instanceKlass *sik = instanceKlass::cast(klassOop(super_ifs->obj_at(j))); | |
585 add_new_mirandas_to_list(mirandas, sik->methods(), class_methods, super); | |
586 } | |
587 } | |
588 } | |
589 | |
590 // get number of mirandas | |
591 int klassVtable::get_num_mirandas(klassOop super, objArrayOop class_methods, objArrayOop local_interfaces) { | |
592 ResourceMark rm; | |
593 GrowableArray<methodOop>* mirandas = new GrowableArray<methodOop>(20); | |
594 get_mirandas(mirandas, super, class_methods, local_interfaces); | |
595 return mirandas->length(); | |
596 } | |
597 | |
598 // fill in mirandas | |
599 void klassVtable::fill_in_mirandas(int& initialized) { | |
600 ResourceMark rm; | |
601 GrowableArray<methodOop>* mirandas = new GrowableArray<methodOop>(20); | |
602 instanceKlass *this_ik = ik(); | |
603 get_mirandas(mirandas, this_ik->super(), this_ik->methods(), this_ik->local_interfaces()); | |
604 int num_mirandas = mirandas->length(); | |
605 for (int i = 0; i < num_mirandas; i++) { | |
606 put_method_at(mirandas->at(i), initialized); | |
607 initialized++; | |
608 } | |
609 } | |
610 | |
611 void klassVtable::copy_vtable_to(vtableEntry* start) { | |
612 Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size()); | |
613 } | |
614 | |
615 void klassVtable::adjust_method_entries(methodOop* old_methods, methodOop* new_methods, | |
616 int methods_length, bool * trace_name_printed) { | |
617 // search the vtable for uses of either obsolete or EMCP methods | |
618 for (int j = 0; j < methods_length; j++) { | |
619 methodOop old_method = old_methods[j]; | |
620 methodOop new_method = new_methods[j]; | |
621 | |
622 // In the vast majority of cases we could get the vtable index | |
623 // by using: old_method->vtable_index() | |
624 // However, there are rare cases, eg. sun.awt.X11.XDecoratedPeer.getX() | |
625 // in sun.awt.X11.XFramePeer where methods occur more than once in the | |
626 // vtable, so, alas, we must do an exhaustive search. | |
627 for (int index = 0; index < length(); index++) { | |
628 if (unchecked_method_at(index) == old_method) { | |
629 put_method_at(new_method, index); | |
630 | |
631 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { | |
632 if (!(*trace_name_printed)) { | |
633 // RC_TRACE_MESG macro has an embedded ResourceMark | |
634 RC_TRACE_MESG(("adjust: name=%s", | |
635 Klass::cast(old_method->method_holder())->external_name())); | |
636 *trace_name_printed = true; | |
637 } | |
638 // RC_TRACE macro has an embedded ResourceMark | |
639 RC_TRACE(0x00100000, ("vtable method update: %s(%s)", | |
640 new_method->name()->as_C_string(), | |
641 new_method->signature()->as_C_string())); | |
642 } | |
643 } | |
644 } | |
645 } | |
646 } | |
647 | |
3245
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
648 // CDS/RedefineClasses support - clear vtables so they can be reinitialized |
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
649 void klassVtable::clear_vtable() { |
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
650 for (int i = 0; i < _length; i++) table()[i].clear(); |
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
651 } |
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
652 |
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
653 bool klassVtable::is_initialized() { |
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
654 return _length == 0 || table()[0].method() != NULL; |
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
655 } |
8ce625481709
7032407: Crash in LinkResolver::runtime_resolve_virtual_method()
coleenp
parents:
2376
diff
changeset
|
656 |
0 | 657 |
658 // Garbage collection | |
659 void klassVtable::oop_follow_contents() { | |
660 int len = length(); | |
661 for (int i = 0; i < len; i++) { | |
662 MarkSweep::mark_and_push(adr_method_at(i)); | |
663 } | |
664 } | |
665 | |
666 #ifndef SERIALGC | |
667 void klassVtable::oop_follow_contents(ParCompactionManager* cm) { | |
668 int len = length(); | |
669 for (int i = 0; i < len; i++) { | |
670 PSParallelCompact::mark_and_push(cm, adr_method_at(i)); | |
671 } | |
672 } | |
673 #endif // SERIALGC | |
674 | |
675 void klassVtable::oop_adjust_pointers() { | |
676 int len = length(); | |
677 for (int i = 0; i < len; i++) { | |
678 MarkSweep::adjust_pointer(adr_method_at(i)); | |
679 } | |
680 } | |
681 | |
682 #ifndef SERIALGC | |
683 void klassVtable::oop_update_pointers(ParCompactionManager* cm) { | |
684 const int n = length(); | |
685 for (int i = 0; i < n; i++) { | |
686 PSParallelCompact::adjust_pointer(adr_method_at(i)); | |
687 } | |
688 } | |
689 #endif // SERIALGC | |
690 | |
691 // Iterators | |
692 void klassVtable::oop_oop_iterate(OopClosure* blk) { | |
693 int len = length(); | |
694 for (int i = 0; i < len; i++) { | |
695 blk->do_oop(adr_method_at(i)); | |
696 } | |
697 } | |
698 | |
699 void klassVtable::oop_oop_iterate_m(OopClosure* blk, MemRegion mr) { | |
700 int len = length(); | |
701 int i; | |
702 for (i = 0; i < len; i++) { | |
703 if ((HeapWord*)adr_method_at(i) >= mr.start()) break; | |
704 } | |
705 for (; i < len; i++) { | |
706 oop* adr = adr_method_at(i); | |
707 if ((HeapWord*)adr < mr.end()) blk->do_oop(adr); | |
708 } | |
709 } | |
710 | |
711 //----------------------------------------------------------------------------------------- | |
712 // Itable code | |
713 | |
714 // Initialize a itableMethodEntry | |
715 void itableMethodEntry::initialize(methodOop m) { | |
716 if (m == NULL) return; | |
717 | |
718 _method = m; | |
719 } | |
720 | |
721 klassItable::klassItable(instanceKlassHandle klass) { | |
722 _klass = klass; | |
723 | |
724 if (klass->itable_length() > 0) { | |
725 itableOffsetEntry* offset_entry = (itableOffsetEntry*)klass->start_of_itable(); | |
726 if (offset_entry != NULL && offset_entry->interface_klass() != NULL) { // Check that itable is initialized | |
727 // First offset entry points to the first method_entry | |
728 intptr_t* method_entry = (intptr_t *)(((address)klass->as_klassOop()) + offset_entry->offset()); | |
729 intptr_t* end = klass->end_of_itable(); | |
730 | |
731 _table_offset = (intptr_t*)offset_entry - (intptr_t*)klass->as_klassOop(); | |
732 _size_offset_table = (method_entry - ((intptr_t*)offset_entry)) / itableOffsetEntry::size(); | |
733 _size_method_table = (end - method_entry) / itableMethodEntry::size(); | |
734 assert(_table_offset >= 0 && _size_offset_table >= 0 && _size_method_table >= 0, "wrong computation"); | |
735 return; | |
736 } | |
737 } | |
738 | |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
739 // The length of the itable was either zero, or it has not yet been initialized. |
0 | 740 _table_offset = 0; |
741 _size_offset_table = 0; | |
742 _size_method_table = 0; | |
743 } | |
744 | |
745 // Garbage Collection | |
746 | |
747 void klassItable::oop_follow_contents() { | |
748 // offset table | |
749 itableOffsetEntry* ioe = offset_entry(0); | |
750 for(int i = 0; i < _size_offset_table; i++) { | |
751 MarkSweep::mark_and_push((oop*)&ioe->_interface); | |
752 ioe++; | |
753 } | |
754 | |
755 // method table | |
756 itableMethodEntry* ime = method_entry(0); | |
757 for(int j = 0; j < _size_method_table; j++) { | |
758 MarkSweep::mark_and_push((oop*)&ime->_method); | |
759 ime++; | |
760 } | |
761 } | |
762 | |
763 #ifndef SERIALGC | |
764 void klassItable::oop_follow_contents(ParCompactionManager* cm) { | |
765 // offset table | |
766 itableOffsetEntry* ioe = offset_entry(0); | |
767 for(int i = 0; i < _size_offset_table; i++) { | |
768 PSParallelCompact::mark_and_push(cm, (oop*)&ioe->_interface); | |
769 ioe++; | |
770 } | |
771 | |
772 // method table | |
773 itableMethodEntry* ime = method_entry(0); | |
774 for(int j = 0; j < _size_method_table; j++) { | |
775 PSParallelCompact::mark_and_push(cm, (oop*)&ime->_method); | |
776 ime++; | |
777 } | |
778 } | |
779 #endif // SERIALGC | |
780 | |
781 void klassItable::oop_adjust_pointers() { | |
782 // offset table | |
783 itableOffsetEntry* ioe = offset_entry(0); | |
784 for(int i = 0; i < _size_offset_table; i++) { | |
785 MarkSweep::adjust_pointer((oop*)&ioe->_interface); | |
786 ioe++; | |
787 } | |
788 | |
789 // method table | |
790 itableMethodEntry* ime = method_entry(0); | |
791 for(int j = 0; j < _size_method_table; j++) { | |
792 MarkSweep::adjust_pointer((oop*)&ime->_method); | |
793 ime++; | |
794 } | |
795 } | |
796 | |
797 #ifndef SERIALGC | |
798 void klassItable::oop_update_pointers(ParCompactionManager* cm) { | |
799 // offset table | |
800 itableOffsetEntry* ioe = offset_entry(0); | |
801 for(int i = 0; i < _size_offset_table; i++) { | |
802 PSParallelCompact::adjust_pointer((oop*)&ioe->_interface); | |
803 ioe++; | |
804 } | |
805 | |
806 // method table | |
807 itableMethodEntry* ime = method_entry(0); | |
808 for(int j = 0; j < _size_method_table; j++) { | |
809 PSParallelCompact::adjust_pointer((oop*)&ime->_method); | |
810 ime++; | |
811 } | |
812 } | |
813 #endif // SERIALGC | |
814 | |
815 // Iterators | |
816 void klassItable::oop_oop_iterate(OopClosure* blk) { | |
817 // offset table | |
818 itableOffsetEntry* ioe = offset_entry(0); | |
819 for(int i = 0; i < _size_offset_table; i++) { | |
820 blk->do_oop((oop*)&ioe->_interface); | |
821 ioe++; | |
822 } | |
823 | |
824 // method table | |
825 itableMethodEntry* ime = method_entry(0); | |
826 for(int j = 0; j < _size_method_table; j++) { | |
827 blk->do_oop((oop*)&ime->_method); | |
828 ime++; | |
829 } | |
830 } | |
831 | |
832 void klassItable::oop_oop_iterate_m(OopClosure* blk, MemRegion mr) { | |
833 // offset table | |
834 itableOffsetEntry* ioe = offset_entry(0); | |
835 for(int i = 0; i < _size_offset_table; i++) { | |
836 oop* adr = (oop*)&ioe->_interface; | |
837 if (mr.contains(adr)) blk->do_oop(adr); | |
838 ioe++; | |
839 } | |
840 | |
841 // method table | |
842 itableMethodEntry* ime = method_entry(0); | |
843 for(int j = 0; j < _size_method_table; j++) { | |
844 oop* adr = (oop*)&ime->_method; | |
845 if (mr.contains(adr)) blk->do_oop(adr); | |
846 ime++; | |
847 } | |
848 } | |
849 | |
850 | |
851 static int initialize_count = 0; | |
852 | |
853 // Initialization | |
854 void klassItable::initialize_itable(bool checkconstraints, TRAPS) { | |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
855 // Cannot be setup doing bootstrapping, interfaces don't have |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
856 // itables, and klass with only ones entry have empty itables |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
857 if (Universe::is_bootstrapping() || |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
858 _klass->is_interface() || |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
859 _klass->itable_length() == itableOffsetEntry::size()) return; |
0 | 860 |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
861 // There's alway an extra itable entry so we can null-terminate it. |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
862 guarantee(size_offset_table() >= 1, "too small"); |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
863 int num_interfaces = size_offset_table() - 1; |
0 | 864 if (num_interfaces > 0) { |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
865 if (TraceItables) tty->print_cr("%3d: Initializing itables for %s", ++initialize_count, |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
866 _klass->name()->as_C_string()); |
0 | 867 |
868 | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
869 // Iterate through all interfaces |
0 | 870 int i; |
871 for(i = 0; i < num_interfaces; i++) { | |
872 itableOffsetEntry* ioe = offset_entry(i); | |
873 KlassHandle interf_h (THREAD, ioe->interface_klass()); | |
874 assert(interf_h() != NULL && ioe->offset() != 0, "bad offset entry in itable"); | |
875 initialize_itable_for_interface(ioe->offset(), interf_h, checkconstraints, CHECK); | |
876 } | |
877 | |
878 } | |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
879 // Check that the last entry is empty |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
880 itableOffsetEntry* ioe = offset_entry(size_offset_table() - 1); |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
881 guarantee(ioe->interface_klass() == NULL && ioe->offset() == 0, "terminator entry missing"); |
0 | 882 } |
883 | |
884 | |
885 void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) { | |
886 objArrayHandle methods(THREAD, instanceKlass::cast(interf_h())->methods()); | |
887 int nof_methods = methods()->length(); | |
888 HandleMark hm; | |
889 KlassHandle klass = _klass; | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
676
diff
changeset
|
890 assert(nof_methods > 0, "at least one method must exist for interface to be in vtable"); |
0 | 891 Handle interface_loader (THREAD, instanceKlass::cast(interf_h())->class_loader()); |
892 int ime_num = 0; | |
893 | |
894 // Skip first methodOop if it is a class initializer | |
2334
dbad0519a1c4
6845426: non-static <clinit> method with no args is called during the class initialization process
kamg
parents:
2227
diff
changeset
|
895 int i = ((methodOop)methods()->obj_at(0))->is_static_initializer() ? 1 : 0; |
0 | 896 |
897 // m, method_name, method_signature, klass reset each loop so they | |
898 // don't need preserving across check_signature_loaders call | |
899 // methods needs a handle in case of gc from check_signature_loaders | |
900 for(; i < nof_methods; i++) { | |
901 methodOop m = (methodOop)methods()->obj_at(i); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
902 Symbol* method_name = m->name(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2018
diff
changeset
|
903 Symbol* method_signature = m->signature(); |
0 | 904 |
905 // This is same code as in Linkresolver::lookup_instance_method_in_klasses | |
906 methodOop target = klass->uncached_lookup_method(method_name, method_signature); | |
907 while (target != NULL && target->is_static()) { | |
908 // continue with recursive lookup through the superclass | |
909 klassOop super = Klass::cast(target->method_holder())->super(); | |
910 target = (super == NULL) ? methodOop(NULL) : Klass::cast(super)->uncached_lookup_method(method_name, method_signature); | |
911 } | |
912 if (target == NULL || !target->is_public() || target->is_abstract()) { | |
913 // Entry do not resolve. Leave it empty | |
914 } else { | |
915 // Entry did resolve, check loader constraints before initializing | |
916 // if checkconstraints requested | |
917 methodHandle target_h (THREAD, target); // preserve across gc | |
918 if (checkconstraints) { | |
919 Handle method_holder_loader (THREAD, instanceKlass::cast(target->method_holder())->class_loader()); | |
920 if (method_holder_loader() != interface_loader()) { | |
921 ResourceMark rm(THREAD); | |
922 char* failed_type_name = | |
923 SystemDictionary::check_signature_loaders(method_signature, | |
924 method_holder_loader, | |
925 interface_loader, | |
926 true, CHECK); | |
927 if (failed_type_name != NULL) { | |
928 const char* msg = "loader constraint violation in interface " | |
929 "itable initialization: when resolving method \"%s\" the class" | |
930 " loader (instance of %s) of the current class, %s, " | |
931 "and the class loader (instance of %s) for interface " | |
932 "%s have different Class objects for the type %s " | |
933 "used in the signature"; | |
934 char* sig = target_h()->name_and_sig_as_C_string(); | |
935 const char* loader1 = SystemDictionary::loader_name(method_holder_loader()); | |
936 char* current = klass->name()->as_C_string(); | |
937 const char* loader2 = SystemDictionary::loader_name(interface_loader()); | |
938 char* iface = instanceKlass::cast(interf_h())->name()->as_C_string(); | |
939 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + | |
940 strlen(current) + strlen(loader2) + strlen(iface) + | |
941 strlen(failed_type_name); | |
942 char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); | |
943 jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2, | |
944 iface, failed_type_name); | |
945 THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); | |
946 } | |
947 } | |
948 } | |
949 | |
950 // ime may have moved during GC so recalculate address | |
951 itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target_h()); | |
952 } | |
953 // Progress to next entry | |
954 ime_num++; | |
955 } | |
956 } | |
957 | |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
958 // Update entry for specific methodOop |
0 | 959 void klassItable::initialize_with_method(methodOop m) { |
960 itableMethodEntry* ime = method_entry(0); | |
961 for(int i = 0; i < _size_method_table; i++) { | |
962 if (ime->method() == m) { | |
963 ime->initialize(m); | |
964 } | |
965 ime++; | |
966 } | |
967 } | |
968 | |
969 void klassItable::adjust_method_entries(methodOop* old_methods, methodOop* new_methods, | |
970 int methods_length, bool * trace_name_printed) { | |
971 // search the itable for uses of either obsolete or EMCP methods | |
972 for (int j = 0; j < methods_length; j++) { | |
973 methodOop old_method = old_methods[j]; | |
974 methodOop new_method = new_methods[j]; | |
975 itableMethodEntry* ime = method_entry(0); | |
976 | |
610
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
196
diff
changeset
|
977 // The itable can describe more than one interface and the same |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
196
diff
changeset
|
978 // method signature can be specified by more than one interface. |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
196
diff
changeset
|
979 // This means we have to do an exhaustive search to find all the |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
196
diff
changeset
|
980 // old_method references. |
0 | 981 for (int i = 0; i < _size_method_table; i++) { |
982 if (ime->method() == old_method) { | |
983 ime->initialize(new_method); | |
984 | |
985 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { | |
986 if (!(*trace_name_printed)) { | |
987 // RC_TRACE_MESG macro has an embedded ResourceMark | |
988 RC_TRACE_MESG(("adjust: name=%s", | |
989 Klass::cast(old_method->method_holder())->external_name())); | |
990 *trace_name_printed = true; | |
991 } | |
992 // RC_TRACE macro has an embedded ResourceMark | |
993 RC_TRACE(0x00200000, ("itable method update: %s(%s)", | |
994 new_method->name()->as_C_string(), | |
995 new_method->signature()->as_C_string())); | |
996 } | |
652
4aaa9f5e02a8
4766230: Hotspot vtable inconsistencies cause core dumps. 6579515. 6582242.
acorn
parents:
610
diff
changeset
|
997 break; |
0 | 998 } |
999 ime++; | |
1000 } | |
1001 } | |
1002 } | |
1003 | |
1004 | |
1005 // Setup | |
1006 class InterfaceVisiterClosure : public StackObj { | |
1007 public: | |
1008 virtual void doit(klassOop intf, int method_count) = 0; | |
1009 }; | |
1010 | |
1011 // Visit all interfaces with at-least one method (excluding <clinit>) | |
1012 void visit_all_interfaces(objArrayOop transitive_intf, InterfaceVisiterClosure *blk) { | |
1013 // Handle array argument | |
1014 for(int i = 0; i < transitive_intf->length(); i++) { | |
1015 klassOop intf = (klassOop)transitive_intf->obj_at(i); | |
1016 assert(Klass::cast(intf)->is_interface(), "sanity check"); | |
1017 | |
1018 // Find no. of methods excluding a <clinit> | |
1019 int method_count = instanceKlass::cast(intf)->methods()->length(); | |
1020 if (method_count > 0) { | |
1021 methodOop m = (methodOop)instanceKlass::cast(intf)->methods()->obj_at(0); | |
1022 assert(m != NULL && m->is_method(), "sanity check"); | |
1023 if (m->name() == vmSymbols::object_initializer_name()) { | |
1024 method_count--; | |
1025 } | |
1026 } | |
1027 | |
1028 // Only count interfaces with at least one method | |
1029 if (method_count > 0) { | |
1030 blk->doit(intf, method_count); | |
1031 } | |
1032 } | |
1033 } | |
1034 | |
1035 class CountInterfacesClosure : public InterfaceVisiterClosure { | |
1036 private: | |
1037 int _nof_methods; | |
1038 int _nof_interfaces; | |
1039 public: | |
1040 CountInterfacesClosure() { _nof_methods = 0; _nof_interfaces = 0; } | |
1041 | |
1042 int nof_methods() const { return _nof_methods; } | |
1043 int nof_interfaces() const { return _nof_interfaces; } | |
1044 | |
1045 void doit(klassOop intf, int method_count) { _nof_methods += method_count; _nof_interfaces++; } | |
1046 }; | |
1047 | |
1048 class SetupItableClosure : public InterfaceVisiterClosure { | |
1049 private: | |
1050 itableOffsetEntry* _offset_entry; | |
1051 itableMethodEntry* _method_entry; | |
1052 address _klass_begin; | |
1053 public: | |
1054 SetupItableClosure(address klass_begin, itableOffsetEntry* offset_entry, itableMethodEntry* method_entry) { | |
1055 _klass_begin = klass_begin; | |
1056 _offset_entry = offset_entry; | |
1057 _method_entry = method_entry; | |
1058 } | |
1059 | |
1060 itableMethodEntry* method_entry() const { return _method_entry; } | |
1061 | |
1062 void doit(klassOop intf, int method_count) { | |
1063 int offset = ((address)_method_entry) - _klass_begin; | |
1064 _offset_entry->initialize(intf, offset); | |
1065 _offset_entry++; | |
1066 _method_entry += method_count; | |
1067 } | |
1068 }; | |
1069 | |
1070 int klassItable::compute_itable_size(objArrayHandle transitive_interfaces) { | |
1071 // Count no of interfaces and total number of interface methods | |
1072 CountInterfacesClosure cic; | |
1073 visit_all_interfaces(transitive_interfaces(), &cic); | |
1074 | |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
1075 // There's alway an extra itable entry so we can null-terminate it. |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
1076 int itable_size = calc_itable_size(cic.nof_interfaces() + 1, cic.nof_methods()); |
0 | 1077 |
1078 // Statistics | |
1079 update_stats(itable_size * HeapWordSize); | |
1080 | |
1081 return itable_size; | |
1082 } | |
1083 | |
1084 | |
1085 // Fill out offset table and interface klasses into the itable space | |
1086 void klassItable::setup_itable_offset_table(instanceKlassHandle klass) { | |
1087 if (klass->itable_length() == 0) return; | |
1088 assert(!klass->is_interface(), "Should have zero length itable"); | |
1089 | |
1090 // Count no of interfaces and total number of interface methods | |
1091 CountInterfacesClosure cic; | |
1092 visit_all_interfaces(klass->transitive_interfaces(), &cic); | |
1093 int nof_methods = cic.nof_methods(); | |
1094 int nof_interfaces = cic.nof_interfaces(); | |
1095 | |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
1096 // Add one extra entry so we can null-terminate the table |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
1097 nof_interfaces++; |
0 | 1098 |
1099 assert(compute_itable_size(objArrayHandle(klass->transitive_interfaces())) == | |
1100 calc_itable_size(nof_interfaces, nof_methods), | |
1101 "mismatch calculation of itable size"); | |
1102 | |
1103 // Fill-out offset table | |
1104 itableOffsetEntry* ioe = (itableOffsetEntry*)klass->start_of_itable(); | |
1105 itableMethodEntry* ime = (itableMethodEntry*)(ioe + nof_interfaces); | |
1106 intptr_t* end = klass->end_of_itable(); | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2334
diff
changeset
|
1107 assert((oop*)(ime + nof_methods) <= (oop*)klass->start_of_nonstatic_oop_maps(), "wrong offset calculation (1)"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1108 assert((oop*)(end) == (oop*)(ime + nof_methods), "wrong offset calculation (2)"); |
0 | 1109 |
1110 // Visit all interfaces and initialize itable offset table | |
1111 SetupItableClosure sic((address)klass->as_klassOop(), ioe, ime); | |
1112 visit_all_interfaces(klass->transitive_interfaces(), &sic); | |
1113 | |
1114 #ifdef ASSERT | |
1115 ime = sic.method_entry(); | |
1116 oop* v = (oop*) klass->end_of_itable(); | |
1117 assert( (oop*)(ime) == v, "wrong offset calculation (2)"); | |
1118 #endif | |
1119 } | |
1120 | |
1121 | |
1122 // m must be a method in an interface | |
1123 int klassItable::compute_itable_index(methodOop m) { | |
1124 klassOop intf = m->method_holder(); | |
1125 assert(instanceKlass::cast(intf)->is_interface(), "sanity check"); | |
1126 objArrayOop methods = instanceKlass::cast(intf)->methods(); | |
1127 int index = 0; | |
1128 while(methods->obj_at(index) != m) { | |
1129 index++; | |
1130 assert(index < methods->length(), "should find index for resolve_invoke"); | |
1131 } | |
1132 // Adjust for <clinit>, which is left out of table if first method | |
2334
dbad0519a1c4
6845426: non-static <clinit> method with no args is called during the class initialization process
kamg
parents:
2227
diff
changeset
|
1133 if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->is_static_initializer()) { |
0 | 1134 index--; |
1135 } | |
1136 return index; | |
1137 } | |
1138 | |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1139 |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1140 // inverse to compute_itable_index |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1141 methodOop klassItable::method_for_itable_index(klassOop intf, int itable_index) { |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1142 assert(instanceKlass::cast(intf)->is_interface(), "sanity check"); |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1143 objArrayOop methods = instanceKlass::cast(intf)->methods(); |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1144 |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1145 int index = itable_index; |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1146 // Adjust for <clinit>, which is left out of table if first method |
2334
dbad0519a1c4
6845426: non-static <clinit> method with no args is called during the class initialization process
kamg
parents:
2227
diff
changeset
|
1147 if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->is_static_initializer()) { |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1148 index++; |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1149 } |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1150 |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1151 if (itable_index < 0 || index >= methods->length()) |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1152 return NULL; // help caller defend against bad indexes |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1153 |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1154 methodOop m = (methodOop)methods->obj_at(index); |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1155 assert(compute_itable_index(m) == itable_index, "correct inverse"); |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1156 |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1157 return m; |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1158 } |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
610
diff
changeset
|
1159 |
0 | 1160 void klassVtable::verify(outputStream* st, bool forced) { |
1161 // make sure table is initialized | |
1162 if (!Universe::is_fully_initialized()) return; | |
1163 #ifndef PRODUCT | |
1164 // avoid redundant verifies | |
1165 if (!forced && _verify_count == Universe::verify_count()) return; | |
1166 _verify_count = Universe::verify_count(); | |
1167 #endif | |
1168 oop* end_of_obj = (oop*)_klass() + _klass()->size(); | |
1169 oop* end_of_vtable = (oop *)&table()[_length]; | |
1170 if (end_of_vtable > end_of_obj) { | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
1489
diff
changeset
|
1171 fatal(err_msg("klass %s: klass object too short (vtable extends beyond " |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
1489
diff
changeset
|
1172 "end)", _klass->internal_name())); |
0 | 1173 } |
1174 | |
1175 for (int i = 0; i < _length; i++) table()[i].verify(this, st); | |
1176 // verify consistency with superKlass vtable | |
1177 klassOop super = _klass->super(); | |
1178 if (super != NULL) { | |
1179 instanceKlass* sk = instanceKlass::cast(super); | |
1180 klassVtable* vt = sk->vtable(); | |
1181 for (int i = 0; i < vt->length(); i++) { | |
1182 verify_against(st, vt, i); | |
1183 } | |
1184 } | |
1185 } | |
1186 | |
1187 void klassVtable::verify_against(outputStream* st, klassVtable* vt, int index) { | |
1188 vtableEntry* vte = &vt->table()[index]; | |
1189 if (vte->method()->name() != table()[index].method()->name() || | |
1190 vte->method()->signature() != table()[index].method()->signature()) { | |
1191 fatal("mismatched name/signature of vtable entries"); | |
1192 } | |
1193 } | |
1194 | |
1195 #ifndef PRODUCT | |
1196 void klassVtable::print() { | |
1197 ResourceMark rm; | |
1198 tty->print("klassVtable for klass %s (length %d):\n", _klass->internal_name(), length()); | |
1199 for (int i = 0; i < length(); i++) { | |
1200 table()[i].print(); | |
1201 tty->cr(); | |
1202 } | |
1203 } | |
1204 #endif | |
1205 | |
1206 void vtableEntry::verify(klassVtable* vt, outputStream* st) { | |
1207 NOT_PRODUCT(FlagSetting fs(IgnoreLockingAssertions, true)); | |
1208 assert(method() != NULL, "must have set method"); | |
1209 method()->verify(); | |
1210 // we sub_type, because it could be a miranda method | |
1211 if (!vt->klass()->is_subtype_of(method()->method_holder())) { | |
1212 #ifndef PRODUCT | |
1213 print(); | |
1214 #endif | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
1489
diff
changeset
|
1215 fatal(err_msg("vtableEntry " PTR_FORMAT ": method is from subclass", this)); |
0 | 1216 } |
1217 } | |
1218 | |
1219 #ifndef PRODUCT | |
1220 | |
1221 void vtableEntry::print() { | |
1222 ResourceMark rm; | |
1223 tty->print("vtableEntry %s: ", method()->name()->as_C_string()); | |
1224 if (Verbose) { | |
1225 tty->print("m %#lx ", (address)method()); | |
1226 } | |
1227 } | |
1228 | |
1229 class VtableStats : AllStatic { | |
1230 public: | |
1231 static int no_klasses; // # classes with vtables | |
1232 static int no_array_klasses; // # array classes | |
1233 static int no_instance_klasses; // # instanceKlasses | |
1234 static int sum_of_vtable_len; // total # of vtable entries | |
1235 static int sum_of_array_vtable_len; // total # of vtable entries in array klasses only | |
1236 static int fixed; // total fixed overhead in bytes | |
1237 static int filler; // overhead caused by filler bytes | |
1238 static int entries; // total bytes consumed by vtable entries | |
1239 static int array_entries; // total bytes consumed by array vtable entries | |
1240 | |
1241 static void do_class(klassOop k) { | |
1242 Klass* kl = k->klass_part(); | |
1243 klassVtable* vt = kl->vtable(); | |
1244 if (vt == NULL) return; | |
1245 no_klasses++; | |
1246 if (kl->oop_is_instance()) { | |
1247 no_instance_klasses++; | |
1248 kl->array_klasses_do(do_class); | |
1249 } | |
1250 if (kl->oop_is_array()) { | |
1251 no_array_klasses++; | |
1252 sum_of_array_vtable_len += vt->length(); | |
1253 } | |
1254 sum_of_vtable_len += vt->length(); | |
1255 } | |
1256 | |
1257 static void compute() { | |
1258 SystemDictionary::classes_do(do_class); | |
1259 fixed = no_klasses * oopSize; // vtable length | |
1260 // filler size is a conservative approximation | |
1261 filler = oopSize * (no_klasses - no_instance_klasses) * (sizeof(instanceKlass) - sizeof(arrayKlass) - 1); | |
1262 entries = sizeof(vtableEntry) * sum_of_vtable_len; | |
1263 array_entries = sizeof(vtableEntry) * sum_of_array_vtable_len; | |
1264 } | |
1265 }; | |
1266 | |
1267 int VtableStats::no_klasses = 0; | |
1268 int VtableStats::no_array_klasses = 0; | |
1269 int VtableStats::no_instance_klasses = 0; | |
1270 int VtableStats::sum_of_vtable_len = 0; | |
1271 int VtableStats::sum_of_array_vtable_len = 0; | |
1272 int VtableStats::fixed = 0; | |
1273 int VtableStats::filler = 0; | |
1274 int VtableStats::entries = 0; | |
1275 int VtableStats::array_entries = 0; | |
1276 | |
1277 void klassVtable::print_statistics() { | |
1278 ResourceMark rm; | |
1279 HandleMark hm; | |
1280 VtableStats::compute(); | |
1281 tty->print_cr("vtable statistics:"); | |
1282 tty->print_cr("%6d classes (%d instance, %d array)", VtableStats::no_klasses, VtableStats::no_instance_klasses, VtableStats::no_array_klasses); | |
1283 int total = VtableStats::fixed + VtableStats::filler + VtableStats::entries; | |
1284 tty->print_cr("%6d bytes fixed overhead (refs + vtable object header)", VtableStats::fixed); | |
1285 tty->print_cr("%6d bytes filler overhead", VtableStats::filler); | |
1286 tty->print_cr("%6d bytes for vtable entries (%d for arrays)", VtableStats::entries, VtableStats::array_entries); | |
1287 tty->print_cr("%6d bytes total", total); | |
1288 } | |
1289 | |
1290 bool klassVtable::check_no_old_entries() { | |
1291 // Check that there really is no entry | |
1292 for (int i = 0; i < length(); i++) { | |
1293 methodOop m = unchecked_method_at(i); | |
1294 if (m != NULL) { | |
1295 if (m->is_old()) { | |
1296 return false; | |
1297 } | |
1298 } | |
1299 } | |
1300 return true; | |
1301 } | |
1302 | |
1303 void klassVtable::dump_vtable() { | |
1304 tty->print_cr("vtable dump --"); | |
1305 for (int i = 0; i < length(); i++) { | |
1306 methodOop m = unchecked_method_at(i); | |
1307 if (m != NULL) { | |
1308 tty->print(" (%5d) ", i); | |
1309 m->access_flags().print_on(tty); | |
1310 tty->print(" -- "); | |
1311 m->print_name(tty); | |
1312 tty->cr(); | |
1313 } | |
1314 } | |
1315 } | |
1316 | |
1317 int klassItable::_total_classes; // Total no. of classes with itables | |
1318 long klassItable::_total_size; // Total no. of bytes used for itables | |
1319 | |
1320 void klassItable::print_statistics() { | |
1321 tty->print_cr("itable statistics:"); | |
1322 tty->print_cr("%6d classes with itables", _total_classes); | |
1323 tty->print_cr("%6d K uses for itables (average by class: %d bytes)", _total_size / K, _total_size / _total_classes); | |
1324 } | |
1325 | |
1326 #endif // PRODUCT |