7194669: CodeCache::mark_for_deoptimization should avoid verifying dependencies multiple times

Avoid verifying dependencies multiple times by caching verified dependencies

Reviewed-by: kvn, twisti, roland
This commit is contained in:
Albert Noll 2014-01-15 06:16:55 +01:00
parent b1c92a140b
commit 2f84f7d5fc
5 changed files with 148 additions and 44 deletions

View file

@ -596,20 +596,13 @@ void CodeCache::clear_inline_caches() {
}
#ifndef PRODUCT
// used to keep track of how much time is spent in mark_for_deoptimization
// Keeps track of time spent for checking dependencies
static elapsedTimer dependentCheckTime;
static int dependentCheckCount = 0;
#endif // PRODUCT
#endif
int CodeCache::mark_for_deoptimization(DepChange& changes) {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
#ifndef PRODUCT
dependentCheckTime.start();
dependentCheckCount++;
#endif // PRODUCT
int number_of_marked_CodeBlobs = 0;
// search the hierarchy looking for nmethods which are affected by the loading of this class
@ -617,32 +610,23 @@ int CodeCache::mark_for_deoptimization(DepChange& changes) {
// then search the interfaces this class implements looking for nmethods
// which might be dependent of the fact that an interface only had one
// implementor.
{ No_Safepoint_Verifier nsv;
for (DepChange::ContextStream str(changes, nsv); str.next(); ) {
Klass* d = str.klass();
number_of_marked_CodeBlobs += InstanceKlass::cast(d)->mark_dependent_nmethods(changes);
}
}
if (VerifyDependencies) {
// Turn off dependency tracing while actually testing deps.
NOT_PRODUCT( FlagSetting fs(TraceDependencies, false) );
FOR_ALL_ALIVE_NMETHODS(nm) {
if (!nm->is_marked_for_deoptimization() &&
nm->check_all_dependencies()) {
ResourceMark rm;
tty->print_cr("Should have been marked for deoptimization:");
changes.print();
nm->print();
nm->print_dependencies();
}
}
// nmethod::check_all_dependencies works only correctly, if no safepoint
// can happen
No_Safepoint_Verifier nsv;
for (DepChange::ContextStream str(changes, nsv); str.next(); ) {
Klass* d = str.klass();
number_of_marked_CodeBlobs += InstanceKlass::cast(d)->mark_dependent_nmethods(changes);
}
#ifndef PRODUCT
dependentCheckTime.stop();
#endif // PRODUCT
if (VerifyDependencies) {
// Object pointers are used as unique identifiers for dependency arguments. This
// is only possible if no safepoint, i.e., GC occurs during the verification code.
dependentCheckTime.start();
nmethod::check_all_dependencies(changes);
dependentCheckTime.stop();
}
#endif
return number_of_marked_CodeBlobs;
}
@ -899,9 +883,7 @@ void CodeCache::print() {
}
tty->print_cr("CodeCache:");
tty->print_cr("nmethod dependency checking time %f", dependentCheckTime.seconds(),
dependentCheckTime.seconds() / dependentCheckCount);
tty->print_cr("nmethod dependency checking time %fs", dependentCheckTime.seconds());
if (!live.is_empty()) {
live.print("live");