src/share/vm/oops/cpCache.cpp

Print this page

        

@@ -453,11 +453,10 @@
         // RC_TRACE macro has an embedded ResourceMark
         RC_TRACE(0x00400000, ("cpc vf-entry update: %s(%s)",
           new_method->name()->as_C_string(),
           new_method->signature()->as_C_string()));
       }
-
       return true;
     }
 
     // f1() is not used with virtual entries so bail out
     return false;

@@ -481,11 +480,10 @@
       // RC_TRACE macro has an embedded ResourceMark
       RC_TRACE(0x00400000, ("cpc entry update: %s(%s)",
         new_method->name()->as_C_string(),
         new_method->signature()->as_C_string()));
     }
-
     return true;
   }
 
   return false;
 }

@@ -539,10 +537,39 @@
   }
 
   // the method is in the interesting class so the entry is interesting
   return true;
 }
+
+Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
+  if (!is_method_entry()) {
+    // not a method entry so not interesting by default
+    return NULL;
+  }
+  Method* m = NULL;
+  if (is_vfinal()) {
+    // virtual and final so _f2 contains method ptr instead of vtable index
+    m = f2_as_vfinal_method();
+  } else if (is_f1_null()) {
+    // NULL _f1 means this is a virtual entry so also not interesting
+    return NULL;
+  } else {
+    if (!(_f1->is_method())) {
+      // _f1 can also contain a Klass* for an interface
+      return NULL;
+    }
+    m = f1_as_method();
+  }
+  assert(m != NULL && m->is_method(), "sanity check");
+  if (m == NULL || !m->is_method() || m->method_holder() != k) {
+    // robustness for above sanity checks or method is not in
+    // the interesting class
+    return NULL;
+  }
+  // the method is in the interesting class so the entry is interesting
+  return m;
+}
 #endif // INCLUDE_JVMTI
 
 void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
   // print separator
   if (index == 0) st->print_cr("                 -------------");

@@ -647,10 +674,32 @@
         // break out and get to the next interesting entry if there one
         break;
       }
     }
   }
+}
+
+// If any entry of this ConstantPoolCache points to any of
+// old_methods, replace it with the corresponding new_method.
+void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
+  for (int i = 0; i < length(); i++) {
+    ConstantPoolCacheEntry* entry = entry_at(i);
+    Method* old_method = entry->get_interesting_method_entry(holder);
+    if (old_method == NULL || !old_method->is_old()) {
+      continue; // skip uninteresting entries
+    }
+    if (old_method->is_deleted()) {
+      // clean up entries with deleted methods
+      entry->initialize_entry(entry->constant_pool_index());
+      continue;
+    }
+    Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
+    assert(new_method != NULL, "method_with_idnum() should not be NULL");
+    if (old_method != new_method) {
+      entry_at(i)->adjust_method_entry(old_method, new_method, trace_name_printed);
+    }
+  }
 }
 
 // the constant pool cache should never contain old or obsolete methods
 bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
   for (int i = 1; i < length(); i++) {