--- a/hotspot/src/share/vm/runtime/synchronizer.cpp Sat Jul 18 04:53:32 2015 +0200
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Tue Jul 21 07:28:37 2015 -0700
@@ -86,6 +86,8 @@
} \
}
+#define HOTSPOT_MONITOR_PROBE_notify HOTSPOT_MONITOR_NOTIFY
+#define HOTSPOT_MONITOR_PROBE_notifyAll HOTSPOT_MONITOR_NOTIFYALL
#define HOTSPOT_MONITOR_PROBE_waited HOTSPOT_MONITOR_WAITED
#define DTRACE_MONITOR_PROBE(probe, monitor, obj, thread) \
@@ -146,6 +148,58 @@
// operators: safepoints or indefinite blocking (blocking that might span a
// safepoint) are forbidden. Generally the thread_state() is _in_Java upon
// entry.
+//
+// Consider: An interesting optimization is to have the JIT recognize the
+// following common idiom:
+// synchronized (someobj) { .... ; notify(); }
+// That is, we find a notify() or notifyAll() call that immediately precedes
+// the monitorexit operation. In that case the JIT could fuse the operations
+// into a single notifyAndExit() runtime primitive.
+
+bool ObjectSynchronizer::quick_notify(oopDesc * obj, Thread * self, bool all) {
+ assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
+ assert(self->is_Java_thread(), "invariant");
+ assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant");
+ No_Safepoint_Verifier nsv;
+ if (obj == NULL) return false; // slow-path for invalid obj
+ const markOop mark = obj->mark();
+
+ if (mark->has_locker() && self->is_lock_owned((address)mark->locker())) {
+ // Degenerate notify
+ // stack-locked by caller so by definition the implied waitset is empty.
+ return true;
+ }
+
+ if (mark->has_monitor()) {
+ ObjectMonitor * const mon = mark->monitor();
+ assert(mon->object() == obj, "invariant");
+ if (mon->owner() != self) return false; // slow-path for IMS exception
+
+ if (mon->first_waiter() != NULL) {
+ // We have one or more waiters. Since this is an inflated monitor
+ // that we own, we can transfer one or more threads from the waitset
+ // to the entrylist here and now, avoiding the slow-path.
+ if (all) {
+ DTRACE_MONITOR_PROBE(notifyAll, mon, obj, self);
+ } else {
+ DTRACE_MONITOR_PROBE(notify, mon, obj, self);
+ }
+ int tally = 0;
+ do {
+ mon->INotify(self);
+ ++tally;
+ } while (mon->first_waiter() != NULL && all);
+ if (ObjectMonitor::_sync_Notifications != NULL) {
+ ObjectMonitor::_sync_Notifications->inc(tally);
+ }
+ }
+ return true;
+ }
+
+ // biased locking and any other IMS exception states take the slow-path
+ return false;
+}
+
// The LockNode emitted directly at the synchronization site would have
// been too big if it were to have included support for the cases of inflated
@@ -1451,8 +1505,7 @@
// This is an unfortunate aspect of this design.
enum ManifestConstants {
- ClearResponsibleAtSTW = 0,
- MaximumRecheckInterval = 1000
+ ClearResponsibleAtSTW = 0
};
// Deflate a single monitor if not in-use