8209950: SIGBUS in CodeHeapState::print_names()
authorlucy
Thu, 30 Aug 2018 09:34:10 +0200
changeset 51591 9183040e34d8
parent 51590 3aaf039a3636
child 51592 1ddd1ec04431
8209950: SIGBUS in CodeHeapState::print_names() Reviewed-by: thartmann, kvn
src/hotspot/share/code/codeHeapState.cpp
src/hotspot/share/code/compiledMethod.cpp
src/hotspot/share/code/compiledMethod.hpp
src/hotspot/share/runtime/sharedRuntime.cpp
--- a/src/hotspot/share/code/codeHeapState.cpp	Thu Aug 30 09:25:38 2018 +0200
+++ b/src/hotspot/share/code/codeHeapState.cpp	Thu Aug 30 09:34:10 2018 +0200
@@ -2168,9 +2168,8 @@
 
         // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
         nmethod*    nm     = this_blob->as_nmethod_or_null();
-        Method*     method = (nm == NULL) ? NULL : nm->method();  // may be uninitialized, i.e. != NULL, but invalid
-        if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) && (cbType != nMethod_inconstruction) &&
-            os::is_readable_pointer(method) && os::is_readable_pointer(method->constants())) {
+        if (CompiledMethod::nmethod_access_is_safe(nm)) {
+          Method* method = nm->method();
           ResourceMark rm;
           //---<  collect all data to locals as quickly as possible  >---
           unsigned int total_size = nm->total_size();
--- a/src/hotspot/share/code/compiledMethod.cpp	Thu Aug 30 09:25:38 2018 +0200
+++ b/src/hotspot/share/code/compiledMethod.cpp	Thu Aug 30 09:34:10 2018 +0200
@@ -619,3 +619,18 @@
     }
   }
 }
+
+// Iterating over all nmethods, e.g. with the help of CodeCache::nmethods_do(fun) was found
+// to not be inherently safe. There is a chance that fields are seen which are not properly
+// initialized. This happens despite the fact that nmethods_do() asserts the CodeCache_lock
+// to be held.
+// To bundle knowledge about necessary checks in one place, this function was introduced.
+// It is not claimed that these checks are sufficient, but they were found to be necessary.
+bool CompiledMethod::nmethod_access_is_safe(nmethod* nm) {
+  Method* method = (nm == NULL) ? NULL : nm->method();  // nm->method() may be uninitialized, i.e. != NULL, but invalid
+  return (nm != NULL) && (method != NULL) && (method->signature() != NULL) &&
+         !nm->is_zombie() && !nm->is_not_installed() &&
+         os::is_readable_pointer(method) &&
+         os::is_readable_pointer(method->constants()) &&
+         os::is_readable_pointer(method->signature());
+}
--- a/src/hotspot/share/code/compiledMethod.hpp	Thu Aug 30 09:25:38 2018 +0200
+++ b/src/hotspot/share/code/compiledMethod.hpp	Thu Aug 30 09:34:10 2018 +0200
@@ -238,6 +238,8 @@
     return _mark_for_deoptimization_status != deoptimize_noupdate;
   }
 
+  static bool nmethod_access_is_safe(nmethod* nm);
+
   // tells whether frames described by this nmethod can be deoptimized
   // note: native wrappers cannot be deoptimized.
   bool can_be_deoptimized() const { return is_java_method(); }
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Thu Aug 30 09:25:38 2018 +0200
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Thu Aug 30 09:34:10 2018 +0200
@@ -2135,16 +2135,14 @@
   static int _max_size;                       // max. arg size seen
 
   static void add_method_to_histogram(nmethod* nm) {
-    // These checks are taken from CodeHeapState::print_names()
-    Method* m = (nm == NULL) ? NULL : nm->method();  // nm->method() may be uninitialized, i.e. != NULL, but invalid
-    if ((nm != NULL) && (m != NULL) && !nm->is_zombie() && !nm->is_not_installed() &&
-        os::is_readable_pointer(m) && os::is_readable_pointer(m->constants())) {
-      ArgumentCount args(m->signature());
-      int arity   = args.size() + (m->is_static() ? 0 : 1);
-      int argsize = m->size_of_parameters();
+    if (CompiledMethod::nmethod_access_is_safe(nm)) {
+      Method* method = nm->method();
+      ArgumentCount args(method->signature());
+      int arity   = args.size() + (method->is_static() ? 0 : 1);
+      int argsize = method->size_of_parameters();
       arity   = MIN2(arity, MAX_ARITY-1);
       argsize = MIN2(argsize, MAX_ARITY-1);
-      int count = nm->method()->compiled_invocation_count();
+      int count = method->compiled_invocation_count();
       _arity_histogram[arity]  += count;
       _size_histogram[argsize] += count;
       _max_arity = MAX2(_max_arity, arity);