changeset 9427:3b1ad311bf91

8258669: fastdebug jvm crashes when do event based tracing for monitor inflation Reviewed-by: phh
author fyang
date Fri, 18 Dec 2020 15:41:43 +0800
parents caca9fa8d833
children 32086319a1c6
files src/share/vm/jfr/recorder/checkpoint/types/jfrType.cpp src/share/vm/runtime/synchronizer.cpp src/share/vm/runtime/synchronizer.hpp
diffstat 3 files changed, 76 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/jfr/recorder/checkpoint/types/jfrType.cpp	Tue Sep 03 10:03:13 2019 +0200
+++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrType.cpp	Fri Dec 18 15:41:43 2020 +0800
@@ -151,13 +151,12 @@
 }
 
 void MonitorInflateCauseConstant::serialize(JfrCheckpointWriter& writer) {
-  // XXX no such counters. implement?
-//  static const u4 nof_entries = ObjectSynchronizer::inflate_cause_nof;
-//  writer.write_count(nof_entries);
-//  for (u4 i = 0; i < nof_entries; ++i) {
-//    writer.write_key(i);
-//    writer.write(ObjectSynchronizer::inflate_cause_name((ObjectSynchronizer::InflateCause)i));
-//  }
+  static const u4 nof_entries = ObjectSynchronizer::inflate_cause_nof;
+  writer.write_count(nof_entries);
+  for (u4 i = 0; i < nof_entries; ++i) {
+    writer.write_key(i);
+    writer.write(ObjectSynchronizer::inflate_cause_name((ObjectSynchronizer::InflateCause)i));
+  }
 }
 
 void GCCauseConstant::serialize(JfrCheckpointWriter& writer) {
--- a/src/share/vm/runtime/synchronizer.cpp	Tue Sep 03 10:03:13 2019 +0200
+++ b/src/share/vm/runtime/synchronizer.cpp	Fri Dec 18 15:41:43 2020 +0800
@@ -216,7 +216,9 @@
      }
   }
 
-  ObjectSynchronizer::inflate(THREAD, object)->exit (true, THREAD) ;
+  ObjectSynchronizer::inflate(THREAD,
+                              object,
+                              inflate_cause_vm_internal)->exit(true, THREAD);
 }
 
 // -----------------------------------------------------------------------------
@@ -258,7 +260,9 @@
   // must be non-zero to avoid looking like a re-entrant lock,
   // and must not look locked either.
   lock->set_displaced_header(markOopDesc::unused_mark());
-  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
+  ObjectSynchronizer::inflate(THREAD,
+                              obj(),
+                              inflate_cause_monitor_enter)->enter(THREAD);
 }
 
 // This routine is used to handle interpreter/compiler slow case
@@ -288,7 +292,9 @@
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
   }
 
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
+                                                       obj(),
+                                                       inflate_cause_vm_internal);
 
   return monitor->complete_exit(THREAD);
 }
@@ -301,7 +307,9 @@
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
   }
 
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
+                                                       obj(),
+                                                       inflate_cause_vm_internal);
 
   monitor->reenter(recursion, THREAD);
 }
@@ -316,7 +324,7 @@
     assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
   }
   THREAD->set_current_pending_monitor_is_from_java(false);
-  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
+  ObjectSynchronizer::inflate(THREAD, obj(), inflate_cause_jni_enter)->enter(THREAD);
   THREAD->set_current_pending_monitor_is_from_java(true);
 }
 
@@ -342,7 +350,9 @@
   }
   assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
 
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj);
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
+                                                       obj,
+                                                       inflate_cause_jni_exit);
   // If this thread has locked the object, exit the monitor.  Note:  can't use
   // monitor->check(CHECK); must exit even if an exception is pending.
   if (monitor->check(THREAD)) {
@@ -385,7 +395,10 @@
     TEVENT (wait - throw IAX) ;
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
   }
-  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
+  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
+                                                       obj(),
+                                                       inflate_cause_wait);
+
   DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
   monitor->wait(millis, true, THREAD);
 
@@ -404,7 +417,9 @@
     TEVENT (wait - throw IAX) ;
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
   }
-  ObjectSynchronizer::inflate(THREAD, obj()) -> wait(millis, false, THREAD) ;
+  ObjectSynchronizer::inflate(THREAD,
+                              obj(),
+                              inflate_cause_wait)->wait(millis, false, THREAD) ;
 }
 
 void ObjectSynchronizer::notify(Handle obj, TRAPS) {
@@ -417,7 +432,9 @@
   if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
     return;
   }
-  ObjectSynchronizer::inflate(THREAD, obj())->notify(THREAD);
+  ObjectSynchronizer::inflate(THREAD,
+                              obj(),
+                              inflate_cause_notify)->notify(THREAD);
 }
 
 // NOTE: see comment of notify()
@@ -431,7 +448,9 @@
   if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
     return;
   }
-  ObjectSynchronizer::inflate(THREAD, obj())->notifyAll(THREAD);
+  ObjectSynchronizer::inflate(THREAD,
+                              obj(),
+                              inflate_cause_notify)->notifyAll(THREAD);
 }
 
 // -----------------------------------------------------------------------------
@@ -686,7 +705,7 @@
   }
 
   // Inflate the monitor to set hash code
-  monitor = ObjectSynchronizer::inflate(Self, obj);
+  monitor = ObjectSynchronizer::inflate(Self, obj, inflate_cause_hash_code);
   // Load displaced header and check it has hash code
   mark = monitor->header();
   assert (mark->is_neutral(), "invariant") ;
@@ -1183,12 +1202,29 @@
     TEVENT (omFlush) ;
 }
 
+const char* ObjectSynchronizer::inflate_cause_name(const InflateCause cause) {
+  switch (cause) {
+    case inflate_cause_vm_internal:    return "VM Internal";
+    case inflate_cause_monitor_enter:  return "Monitor Enter";
+    case inflate_cause_wait:           return "Monitor Wait";
+    case inflate_cause_notify:         return "Monitor Notify";
+    case inflate_cause_hash_code:      return "Monitor Hash Code";
+    case inflate_cause_jni_enter:      return "JNI Monitor Enter";
+    case inflate_cause_jni_exit:       return "JNI Monitor Exit";
+    default:
+      ShouldNotReachHere();
+  }
+  return "Unknown";
+}
+
 static void post_monitor_inflate_event(EventJavaMonitorInflate* event,
-                                       const oop obj) {
+                                       const oop obj,
+                                       const ObjectSynchronizer::InflateCause cause) {
   assert(event != NULL, "invariant");
   assert(event->should_commit(), "invariant");
   event->set_monitorClass(obj->klass());
   event->set_address((uintptr_t)(void*)obj);
+  event->set_cause((u1)cause);
   event->commit();
 }
 
@@ -1200,7 +1236,9 @@
     assert(mark->monitor()->header()->is_neutral(), "monitor must record a good object header");
     return mark->monitor();
   }
-  return ObjectSynchronizer::inflate(Thread::current(), obj);
+  return ObjectSynchronizer::inflate(Thread::current(),
+                                     obj,
+                                     inflate_cause_vm_internal);
 }
 
 
@@ -1208,7 +1246,9 @@
 // multiple locks occupy the same $ line.  Padding might be appropriate.
 
 
-ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) {
+ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self,
+                                                  oop object,
+                                                  const InflateCause cause) {
   // Inflate mutates the heap ...
   // Relaxing assertion for bug 6320749.
   assert (Universe::verify_in_progress() ||
@@ -1347,7 +1387,7 @@
             }
           }
           if (event.should_commit()) {
-            post_monitor_inflate_event(&event, object);
+            post_monitor_inflate_event(&event, object, cause);
           }
           return m ;
       }
@@ -1400,7 +1440,7 @@
         }
       }
       if (event.should_commit()) {
-        post_monitor_inflate_event(&event, object);
+        post_monitor_inflate_event(&event, object, cause);
       }
       return m ;
   }
--- a/src/share/vm/runtime/synchronizer.hpp	Tue Sep 03 10:03:13 2019 +0200
+++ b/src/share/vm/runtime/synchronizer.hpp	Fri Dec 18 15:41:43 2020 +0800
@@ -42,6 +42,18 @@
     owner_none,
     owner_other
   } LockOwnership;
+
+  typedef enum {
+    inflate_cause_vm_internal = 0,
+    inflate_cause_monitor_enter = 1,
+    inflate_cause_wait = 2,
+    inflate_cause_notify = 3,
+    inflate_cause_hash_code = 4,
+    inflate_cause_jni_enter = 5,
+    inflate_cause_jni_exit = 6,
+    inflate_cause_nof = 7 // Number of causes
+  } InflateCause;
+
   // exit must be implemented non-blocking, since the compiler cannot easily handle
   // deoptimization at monitor exit. Hence, it does not take a Handle argument.
 
@@ -90,9 +102,10 @@
   static void omFlush   (Thread * Self) ;
 
   // Inflate light weight monitor to heavy weight monitor
-  static ObjectMonitor* inflate(Thread * Self, oop obj);
+  static ObjectMonitor* inflate(Thread * Self, oop obj, const InflateCause cause);
   // This version is only for internal use
   static ObjectMonitor* inflate_helper(oop obj);
+  static const char* inflate_cause_name(const InflateCause cause);
 
   // Returns the identity hash value for an oop
   // NOTE: It may cause monitor inflation