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