This commit is contained in:
Markus Grönlund 2016-02-04 19:27:39 +01:00
commit 88711a6b2d
5 changed files with 109 additions and 17 deletions

View File

@ -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 intptr_t gListLock = 0; // protects global monitor lists
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 @@ void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
}
}
ObjectSynchronizer::inflate(THREAD, object)->exit(true, THREAD);
ObjectSynchronizer::inflate(THREAD,
object,
inflate_cause_vm_internal)->exit(true, THREAD);
}
// -----------------------------------------------------------------------------
@ -338,7 +346,9 @@ void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
// 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 @@ intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
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 @@ void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
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 @@ void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
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 @@ void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
}
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 @@ int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
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 @@ void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) {
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 @@ void ObjectSynchronizer::notify(Handle obj, TRAPS) {
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 @@ void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
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 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
}
// 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 @@ ObjectMonitor* ObjectSynchronizer::inflate_helper(oop obj) {
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) {
oop object,
const InflateCause cause) {
// 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 @@ ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self,
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 @@ ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self,
object->klass()->external_name());
}
}
if (event.should_commit()) {
post_monitor_inflate_event(event, object, cause);
}
return m;
}
@ -1471,6 +1505,9 @@ ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self,
object->klass()->external_name());
}
}
if (event.should_commit()) {
post_monitor_inflate_event(event, object, cause);
}
return m;
}
}
@ -1742,6 +1779,33 @@ void ObjectSynchronizer::release_monitors_owned_by_thread(TRAPS) {
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

View File

@ -42,6 +42,18 @@ class ObjectSynchronizer : AllStatic {
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 @@ class ObjectSynchronizer : AllStatic {
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

View File

@ -109,6 +109,13 @@ Declares a structure type that can be used in other events.
<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"/>

View File

@ -56,7 +56,8 @@ public:
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"/>

View File

@ -170,12 +170,16 @@ Now we can use the content + data type in declaring event fields.
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 @@ Now we can use the content + data type in declaring event fields.
<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>