8138562: Event based tracing should cover monitor inflation
authordsimms
Thu, 04 Feb 2016 18:28:52 +0100
changeset 35934 76dbe86f3d82
parent 35932 511dd7b5313b
child 35935 a2bae85710af
8138562: Event based tracing should cover monitor inflation Reviewed-by: dcubed, egahlin, mgronlun
hotspot/src/share/vm/runtime/synchronizer.cpp
hotspot/src/share/vm/runtime/synchronizer.hpp
hotspot/src/share/vm/trace/trace.xml
hotspot/src/share/vm/trace/traceEventClasses.xsl
hotspot/src/share/vm/trace/tracetypes.xml
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Thu Feb 04 14:06:43 2016 +0100
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Thu Feb 04 18:28:52 2016 +0100
@@ -42,6 +42,8 @@
 #include "runtime/synchronizer.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/vframe.hpp"
+#include "trace/traceMacros.hpp"
+#include "trace/tracing.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/events.hpp"
 #include "utilities/preserveException.hpp"
@@ -130,6 +132,10 @@
 static volatile int gMonitorFreeCount  = 0;  // # on gFreeList
 static volatile int gMonitorPopulation = 0;  // # Extant -- in circulation
 
+static void post_monitor_inflate_event(EventJavaMonitorInflate&,
+                                       const oop,
+                                       const ObjectSynchronizer::InflateCause);
+
 #define CHAINMARKER (cast_to_oop<intptr_t>(-1))
 
 
@@ -304,7 +310,9 @@
     }
   }
 
-  ObjectSynchronizer::inflate(THREAD, object)->exit(true, THREAD);
+  ObjectSynchronizer::inflate(THREAD,
+                              object,
+                              inflate_cause_vm_internal)->exit(true, THREAD);
 }
 
 // -----------------------------------------------------------------------------
@@ -338,7 +346,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
@@ -368,7 +378,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);
 }
@@ -381,7 +393,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);
 }
@@ -396,7 +410,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);
 }
 
@@ -410,7 +424,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)) {
@@ -453,7 +469,10 @@
     TEVENT(wait - throw IAX);
     THROW_MSG_0(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);
 
@@ -473,7 +492,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) {
@@ -486,7 +507,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()
@@ -500,7 +523,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);
 }
 
 // -----------------------------------------------------------------------------
@@ -749,7 +774,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");
@@ -1283,17 +1308,22 @@
     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);
 }
 
+ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self,
+                                                     oop object,
+                                                     const InflateCause cause) {
 
-ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self,
-                                                     oop object) {
   // Inflate mutates the heap ...
   // Relaxing assertion for bug 6320749.
   assert(Universe::verify_in_progress() ||
          !SafepointSynchronize::is_at_safepoint(), "invariant");
 
+  EventJavaMonitorInflate event;
+
   for (;;) {
     const markOop mark = object->mark();
     assert(!mark->has_bias_pattern(), "invariant");
@@ -1311,6 +1341,7 @@
       assert(inf->header()->is_neutral(), "invariant");
       assert(inf->object() == object, "invariant");
       assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
+      event.cancel(); // let's not post an inflation event, unless we did the deed ourselves
       return inf;
     }
 
@@ -1423,6 +1454,9 @@
                                       object->klass()->external_name());
         }
       }
+      if (event.should_commit()) {
+        post_monitor_inflate_event(event, object, cause);
+      }
       return m;
     }
 
@@ -1471,6 +1505,9 @@
                                     object->klass()->external_name());
       }
     }
+    if (event.should_commit()) {
+      post_monitor_inflate_event(event, object, cause);
+    }
     return m;
   }
 }
@@ -1742,6 +1779,33 @@
   THREAD->clear_pending_exception();
 }
 
+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 ObjectSynchronizer::InflateCause cause) {
+#if INCLUDE_TRACE
+  assert(event.should_commit(), "check outside");
+  event.set_klass(obj->klass());
+  event.set_address((TYPE_ADDRESS)(uintptr_t)(void*)obj);
+  event.set_cause((u1)cause);
+  event.commit();
+#endif
+}
+
 //------------------------------------------------------------------------------
 // Debugging code
 
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp	Thu Feb 04 14:06:43 2016 +0100
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp	Thu Feb 04 18:28:52 2016 +0100
@@ -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.
 
@@ -94,9 +106,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
--- a/hotspot/src/share/vm/trace/trace.xml	Thu Feb 04 14:06:43 2016 +0100
+++ b/hotspot/src/share/vm/trace/trace.xml	Thu Feb 04 18:28:52 2016 +0100
@@ -109,6 +109,13 @@
       <value type="ADDRESS" field="address" label="Monitor Address" description="Address of object waited on" relation="JAVA_MONITOR_ADDRESS"/>
     </event>
 
+    <event id="JavaMonitorInflate" path="java/monitor_inflate" label="Java Monitor Inflated"
+           has_thread="true" has_stacktrace="true" is_instant="false">
+      <value type="CLASS" field="klass" label="Monitor Class"/>
+      <value type="ADDRESS" field="address" label="Monitor Address" relation="JAVA_MONITOR_ADDRESS"/>
+      <value type="INFLATECAUSE" field="cause" label="Cause" description="Cause of inflation"/>
+    </event>
+
     <event id="ReservedStackActivation" path="java/reserved_stack_activation" label="Reserved Stack Activation" description="Activation of Reserved Stack Area caused by stack overflow with ReservedStackAccess annotated method in call stack"
             has_thread="true" has_stacktrace="true" is_instant="true">
         <value type="METHOD" field="method" label="Java Method"/>
--- a/hotspot/src/share/vm/trace/traceEventClasses.xsl	Thu Feb 04 14:06:43 2016 +0100
+++ b/hotspot/src/share/vm/trace/traceEventClasses.xsl	Thu Feb 04 18:28:52 2016 +0100
@@ -56,7 +56,8 @@
   void set_endtime(const Ticks&amp; time) {}
   bool should_commit() const { return false; }
   static bool is_enabled() { return false; }
-  void commit() const {}
+  void commit() {}
+  void cancel() {}
 };
 
   <xsl:apply-templates select="trace/events/struct" mode="empty"/>
--- a/hotspot/src/share/vm/trace/tracetypes.xml	Thu Feb 04 14:06:43 2016 +0100
+++ b/hotspot/src/share/vm/trace/tracetypes.xml	Thu Feb 04 18:28:52 2016 +0100
@@ -170,12 +170,16 @@
                   type="U1" jvm_type="FLAGVALUEORIGIN">
       <value type="UTF8" field="origin" label="origin" />
     </content_type>
-    
+
     <content_type id="CodeBlobType" hr_name="Code Blob Type"
                   type="U1" jvm_type="CODEBLOBTYPE">
       <value type="UTF8" field="type" label="type" />
     </content_type>
 
+    <content_type id="InflateCause" hr_name="Inflation Cause"
+                  type="U1" jvm_type="INFLATECAUSE">
+      <value type="UTF8" field="cause" label="cause" />
+    </content_type>
   </content_types>
 
 
@@ -381,5 +385,8 @@
     <primary_type symbol="CODEBLOBTYPE" datatype="U1"
                   contenttype="CODEBLOBTYPE" type="u1" sizeop="sizeof(u1)" />
 
+    <!-- INFLATECAUSE -->
+    <primary_type symbol="INFLATECAUSE" datatype="U1"
+                  contenttype="INFLATECAUSE" type="u1" sizeop="sizeof(u1)" />
   </primary_types>
 </types>