--- 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