changeset 14860:8762b6b8fbb6

fix scanning of method data for redefined methods
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Thu, 27 Mar 2014 13:11:17 -0700
parents 4f5c312d676e
children 6325d3d82f1b
files src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/methodData.cpp src/share/vm/oops/methodData.hpp
diffstat 3 files changed, 119 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/oops/instanceKlass.cpp	Thu Mar 27 18:35:55 2014 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Thu Mar 27 13:11:17 2014 -0700
@@ -3411,6 +3411,10 @@
               ("purge: %s(%s): prev method @%d in version @%d is alive",
               method->name()->as_C_string(),
               method->signature()->as_C_string(), j, i));
+            if (method->method_data() != NULL) {
+              // Clean out any weak method links
+              method->method_data()->clean_weak_method_links();
+            }
           }
         }
       }
@@ -3420,6 +3424,14 @@
       ("purge: previous version stats: live=%d, deleted=%d", live_count,
       deleted_count));
   }
+
+  Array<Method*>* methods = ik->methods();
+  int num_methods = methods->length();
+  for (int index2 = 0; index2 < num_methods; ++index2) {
+    if (methods->at(index2)->method_data() != NULL) {
+      methods->at(index2)->method_data()->clean_weak_method_links();
+    }
+  }
 }
 
 // External interface for use during class unloading.
--- a/src/share/vm/oops/methodData.cpp	Thu Mar 27 18:35:55 2014 +0100
+++ b/src/share/vm/oops/methodData.cpp	Thu Mar 27 13:11:17 2014 -0700
@@ -426,6 +426,16 @@
     }
   }
 }
+
+void VirtualCallData::clean_weak_method_links() {
+  ReceiverTypeData::clean_weak_method_links();
+  for (uint row = 0; row < method_row_limit(); row++) {
+    Method* p = method(row);
+    if (p != NULL && !p->on_stack()) {
+      clear_method_row(row);
+    }
+  }
+}
 #endif // GRAAL
 
 #ifndef PRODUCT
@@ -1693,3 +1703,85 @@
   clean_extra_data(is_alive);
   verify_extra_data_clean(is_alive);
 }
+
+// Remove SpeculativeTrapData entries that reference a redefined
+// method
+void MethodData::clean_weak_method_extra_data() {
+  DataLayout* dp  = extra_data_base();
+  DataLayout* end = extra_data_limit();
+
+  int shift = 0;
+  for (; dp < end; dp = next_extra(dp)) {
+    switch(dp->tag()) {
+    case DataLayout::speculative_trap_data_tag: {
+      SpeculativeTrapData* data = new SpeculativeTrapData(dp);
+      Method* m = data->method();
+      assert(m != NULL, "should have a method");
+      if (!m->on_stack()) {
+        // "shift" accumulates the number of cells for dead
+        // SpeculativeTrapData entries that have been seen so
+        // far. Following entries must be shifted left by that many
+        // cells to remove the dead SpeculativeTrapData entries.
+        shift += (int)((intptr_t*)next_extra(dp) - (intptr_t*)dp);
+      } else {
+        // Shift this entry left if it follows dead
+        // SpeculativeTrapData entries
+        clean_extra_data_helper(dp, shift);
+      }
+      break;
+    }
+    case DataLayout::bit_data_tag:
+      // Shift this entry left if it follows dead SpeculativeTrapData
+      // entries
+      clean_extra_data_helper(dp, shift);
+      continue;
+    case DataLayout::no_tag:
+    case DataLayout::arg_info_data_tag:
+      // We are at end of the live trap entries. The previous "shift"
+      // cells contain entries that are either dead or were shifted
+      // left. They need to be reset to no_tag
+      clean_extra_data_helper(dp, shift, true);
+      return;
+    default:
+      fatal(err_msg("unexpected tag %d", dp->tag()));
+    }
+  }
+}
+
+// Verify there's no redefined method referenced by a
+// SpeculativeTrapData entry
+void MethodData::verify_weak_method_extra_data_clean() {
+#ifdef ASSERT
+  DataLayout* dp  = extra_data_base();
+  DataLayout* end = extra_data_limit();
+
+  for (; dp < end; dp = next_extra(dp)) {
+    switch(dp->tag()) {
+    case DataLayout::speculative_trap_data_tag: {
+      SpeculativeTrapData* data = new SpeculativeTrapData(dp);
+      Method* m = data->method();
+      assert(m != NULL && m->on_stack(), "Method should exist");
+      break;
+    }
+    case DataLayout::bit_data_tag:
+      continue;
+    case DataLayout::no_tag:
+    case DataLayout::arg_info_data_tag:
+      return;
+    default:
+      fatal(err_msg("unexpected tag %d", dp->tag()));
+    }
+  }
+#endif
+}
+
+void MethodData::clean_weak_method_links() {
+  for (ProfileData* data = first_data();
+       is_valid(data);
+       data = next_data(data)) {
+    data->clean_weak_method_links();
+  }
+
+  clean_weak_method_extra_data();
+  verify_weak_method_extra_data_clean();
+}
--- a/src/share/vm/oops/methodData.hpp	Thu Mar 27 18:35:55 2014 +0100
+++ b/src/share/vm/oops/methodData.hpp	Thu Mar 27 13:11:17 2014 -0700
@@ -257,6 +257,9 @@
 
   // GC support
   void clean_weak_klass_links(BoolObjectClosure* cl);
+
+  // Redefinition support
+  void clean_weak_method_links();
 };
 
 
@@ -514,6 +517,9 @@
   // GC support
   virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {}
 
+  // Redefinition support
+  virtual void clean_weak_method_links() {}
+
   // CI translation: ProfileData can represent both MethodDataOop data
   // as well as CIMethodData data. This function is provided for translating
   // an oop in a ProfileData to the ci equivalent. Generally speaking,
@@ -1429,6 +1435,9 @@
 
   // GC support
   virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure);
+
+  // Redefinition support
+  virtual void clean_weak_method_links();
 #endif
 
 #ifndef PRODUCT
@@ -2294,6 +2303,10 @@
   void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false);
   void verify_extra_data_clean(BoolObjectClosure* is_alive);
 
+  // Redefinition support
+  void clean_weak_method_extra_data();
+  void verify_weak_method_extra_data_clean();
+
 public:
   static int header_size() {
     return sizeof(MethodData)/wordSize;
@@ -2572,6 +2585,8 @@
   static bool profile_return_jsr292_only();
 
   void clean_method_data(BoolObjectClosure* is_alive);
+
+  void clean_weak_method_links();
 };
 
 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP