< prev index next >

src/share/vm/runtime/biasedLocking.cpp

Print this page

        

@@ -29,10 +29,12 @@
 #include "runtime/biasedLocking.hpp"
 #include "runtime/task.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
+#include "jfr/support/jfrThreadId.hpp"
+#include "jfr/jfrEvents.hpp"
 
 static bool _biased_locking_enabled = false;
 BiasedLockingCounters BiasedLocking::_counters;
 
 static GrowableArray<Handle>*  _preserved_oop_stack  = NULL;

@@ -140,12 +142,13 @@
 
   thread->set_cached_monitor_info(info);
   return info;
 }
 
-
-static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) {
+// After the call, *biased_locker will be set to obj->mark()->biased_locker() if biased_locker != NULL,
+// AND it is a living thread. Otherwise it will not be updated, (i.e. the caller is responsible for initialization).
+static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread, JavaThread** biased_locker) {
   markOop mark = obj->mark();
   if (!mark->has_bias_pattern()) {
     if (TraceBiasedLocking) {
       ResourceMark rm;
       tty->print_cr("  (Skipping revocation of object of type %s because it's no longer biased)",

@@ -251,10 +254,17 @@
       // Store the unlocked value into the object's header.
       obj->set_mark(unbiased_prototype);
     }
   }
 
+#if INCLUDE_JFR
+  // If requested, return information on which thread held the bias
+  if (biased_locker != NULL) {
+    *biased_locker = biased_thread;
+  }
+#endif // INCLUDE_JFR
+
   return BiasedLocking::BIAS_REVOKED;
 }
 
 
 enum HeuristicsResult {

@@ -371,11 +381,11 @@
       }
     }
 
     // At this point we're done. All we have to do is potentially
     // adjust the header of the given object to revoke its bias.
-    revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread);
+    revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL);
   } else {
     if (TraceBiasedLocking) {
       ResourceMark rm;
       tty->print_cr("* Disabling biased locking for type %s", klass->external_name());
     }

@@ -393,18 +403,18 @@
       for (int i = 0; i < cached_monitor_info->length(); i++) {
         MonitorInfo* mon_info = cached_monitor_info->at(i);
         oop owner = mon_info->owner();
         markOop mark = owner->mark();
         if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
-          revoke_bias(owner, false, true, requesting_thread);
+          revoke_bias(owner, false, true, requesting_thread, NULL);
         }
       }
     }
 
     // Must force the bias of the passed object to be forcibly revoked
     // as well to ensure guarantees to callers
-    revoke_bias(o, false, true, requesting_thread);
+    revoke_bias(o, false, true, requesting_thread, NULL);
   }
 
   if (TraceBiasedLocking) {
     tty->print_cr("* Ending bulk revocation");
   }

@@ -443,23 +453,26 @@
 protected:
   Handle* _obj;
   GrowableArray<Handle>* _objs;
   JavaThread* _requesting_thread;
   BiasedLocking::Condition _status_code;
+  traceid _biased_locker_id;
 
 public:
   VM_RevokeBias(Handle* obj, JavaThread* requesting_thread)
     : _obj(obj)
     , _objs(NULL)
     , _requesting_thread(requesting_thread)
-    , _status_code(BiasedLocking::NOT_BIASED) {}
+    , _status_code(BiasedLocking::NOT_BIASED)
+    , _biased_locker_id(0) {}
 
   VM_RevokeBias(GrowableArray<Handle>* objs, JavaThread* requesting_thread)
     : _obj(NULL)
     , _objs(objs)
     , _requesting_thread(requesting_thread)
-    , _status_code(BiasedLocking::NOT_BIASED) {}
+    , _status_code(BiasedLocking::NOT_BIASED)
+    , _biased_locker_id(0) {}
 
   virtual VMOp_Type type() const { return VMOp_RevokeBias; }
 
   virtual bool doit_prologue() {
     // Verify that there is actual work to do since the callers just

@@ -484,11 +497,19 @@
   virtual void doit() {
     if (_obj != NULL) {
       if (TraceBiasedLocking) {
         tty->print_cr("Revoking bias with potentially per-thread safepoint:");
       }
-      _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread);
+
+      JavaThread* biased_locker = NULL;
+      _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread, &biased_locker);
+#if INCLUDE_JFR
+      if (biased_locker != NULL) {
+        _biased_locker_id = JFR_THREAD_ID(biased_locker);
+      }
+#endif // INCLUDE_JFR
+
       clean_up_cached_monitor_info();
       return;
     } else {
       if (TraceBiasedLocking) {
         tty->print_cr("Revoking bias with global safepoint:");

@@ -498,10 +519,14 @@
   }
 
   BiasedLocking::Condition status_code() const {
     return _status_code;
   }
+
+  traceid biased_locker() const {
+    return _biased_locker_id;
+  }
 };
 
 
 class VM_BulkRevokeBias : public VM_RevokeBias {
 private:

@@ -607,27 +632,48 @@
       // stale epoch.
       ResourceMark rm;
       if (TraceBiasedLocking) {
         tty->print_cr("Revoking bias by walking my own stack:");
       }
-      BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD);
+      EventBiasedLockSelfRevocation event;
+      BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD, NULL);
       ((JavaThread*) THREAD)->set_cached_monitor_info(NULL);
       assert(cond == BIAS_REVOKED, "why not?");
+      if (event.should_commit()) {
+        event.set_lockClass(k);
+        event.commit();
+      }
       return cond;
     } else {
+      EventBiasedLockRevocation event;
       VM_RevokeBias revoke(&obj, (JavaThread*) THREAD);
       VMThread::execute(&revoke);
+      if (event.should_commit() && (revoke.status_code() != NOT_BIASED)) {
+        event.set_lockClass(k);
+        // Subtract 1 to match the id of events committed inside the safepoint
+        event.set_safepointId(SafepointSynchronize::safepoint_counter() - 1);
+        event.set_previousOwner(revoke.biased_locker());
+        event.commit();
+      }
       return revoke.status_code();
     }
   }
 
   assert((heuristics == HR_BULK_REVOKE) ||
          (heuristics == HR_BULK_REBIAS), "?");
+  EventBiasedLockClassRevocation event;
   VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*) THREAD,
                                 (heuristics == HR_BULK_REBIAS),
                                 attempt_rebias);
   VMThread::execute(&bulk_revoke);
+  if (event.should_commit()) {
+    event.set_revokedClass(obj->klass());
+    event.set_disableBiasing((heuristics != HR_BULK_REBIAS));
+    // Subtract 1 to match the id of events committed inside the safepoint
+    event.set_safepointId(SafepointSynchronize::safepoint_counter() - 1);
+    event.commit();
+  }
   return bulk_revoke.status_code();
 }
 
 
 void BiasedLocking::revoke(GrowableArray<Handle>* objs) {

@@ -643,11 +689,11 @@
 void BiasedLocking::revoke_at_safepoint(Handle h_obj) {
   assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint");
   oop obj = h_obj();
   HeuristicsResult heuristics = update_heuristics(obj, false);
   if (heuristics == HR_SINGLE_REVOKE) {
-    revoke_bias(obj, false, false, NULL);
+    revoke_bias(obj, false, false, NULL, NULL);
   } else if ((heuristics == HR_BULK_REBIAS) ||
              (heuristics == HR_BULK_REVOKE)) {
     bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);
   }
   clean_up_cached_monitor_info();

@@ -659,11 +705,11 @@
   int len = objs->length();
   for (int i = 0; i < len; i++) {
     oop obj = (objs->at(i))();
     HeuristicsResult heuristics = update_heuristics(obj, false);
     if (heuristics == HR_SINGLE_REVOKE) {
-      revoke_bias(obj, false, false, NULL);
+      revoke_bias(obj, false, false, NULL, NULL);
     } else if ((heuristics == HR_BULK_REBIAS) ||
                (heuristics == HR_BULK_REVOKE)) {
       bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);
     }
   }
< prev index next >