hotspot/src/share/vm/runtime/synchronizer.cpp
changeset 35934 76dbe86f3d82
parent 35492 c8c0273e6b91
child 37092 0e56e3c9d545
--- 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