< prev index next >

src/hotspot/share/runtime/biasedLocking.cpp

Print this page




  28 #include "jfr/support/jfrThreadId.hpp"
  29 #include "logging/log.hpp"
  30 #include "memory/resourceArea.hpp"
  31 #include "oops/klass.inline.hpp"
  32 #include "oops/markOop.hpp"
  33 #include "oops/oop.inline.hpp"
  34 #include "runtime/atomic.hpp"
  35 #include "runtime/basicLock.hpp"
  36 #include "runtime/biasedLocking.hpp"
  37 #include "runtime/handles.inline.hpp"
  38 #include "runtime/task.hpp"
  39 #include "runtime/threadSMR.hpp"
  40 #include "runtime/vframe.hpp"
  41 #include "runtime/vmThread.hpp"
  42 #include "runtime/vmOperations.hpp"
  43 
  44 
  45 static bool _biased_locking_enabled = false;
  46 BiasedLockingCounters BiasedLocking::_counters;
  47 
  48 static GrowableArray<Handle>*  _preserved_oop_stack  = NULL;
  49 static GrowableArray<markWord>* _preserved_mark_stack = NULL;
  50 
  51 static void enable_biased_locking(InstanceKlass* k) {
  52   k->set_prototype_header(markWord::biased_locking_prototype());
  53 }
  54 
  55 static void enable_biased_locking() {
  56   _biased_locking_enabled = true;
  57   log_info(biasedlocking)("Biased locking enabled");
  58 }
  59 
  60 class VM_EnableBiasedLocking: public VM_Operation {
  61  public:
  62   VM_EnableBiasedLocking() {}
  63   VMOp_Type type() const          { return VMOp_EnableBiasedLocking; }
  64   Mode evaluation_mode() const    { return _async_safepoint; }
  65   bool is_cheap_allocated() const { return true; }
  66 
  67   void doit() {
  68     // Iterate the class loader data dictionaries enabling biased locking for all


 461           if ((owner->klass() == k_o) && mark.has_bias_pattern()) {
 462             single_revoke_at_safepoint(owner, false, true, requesting_thread, NULL);
 463           }
 464         }
 465       }
 466 
 467       // Must force the bias of the passed object to be forcibly revoked
 468       // as well to ensure guarantees to callers
 469       single_revoke_at_safepoint(o, false, true, requesting_thread, NULL);
 470     }
 471   } // ThreadsListHandle is destroyed here.
 472 
 473   log_info(biasedlocking)("* Ending bulk revocation");
 474 
 475   BiasedLocking::Condition status_code = BIAS_REVOKED;
 476 
 477   if (attempt_rebias_of_object &&
 478       o->mark().has_bias_pattern() &&
 479       klass->prototype_header().has_bias_pattern()) {
 480     markWord new_mark = markWord::encode(requesting_thread, o->mark().age(),
 481                                            klass->prototype_header().bias_epoch());
 482     o->set_mark(new_mark);
 483     status_code = BIAS_REVOKED_AND_REBIASED;
 484     log_info(biasedlocking)("  Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread);
 485   }
 486 
 487   assert(!o->mark().has_bias_pattern() ||
 488          (attempt_rebias_of_object && (o->mark().biased_locker() == requesting_thread)),
 489          "bug in bulk bias revocation");
 490 
 491   return status_code;
 492 }
 493 
 494 
 495 static void clean_up_cached_monitor_info(JavaThread* thread = NULL) {
 496   if (thread != NULL) {
 497     thread->set_cached_monitor_info(NULL);
 498   } else {
 499     // Walk the thread list clearing out the cached monitors
 500     for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
 501       thr->set_cached_monitor_info(NULL);


 675     if (event.should_commit() && revoke.status_code() == BIAS_REVOKED) {
 676       post_revocation_event(&event, obj->klass(), &revoke);
 677     }
 678     assert(!obj->mark().has_bias_pattern(), "invariant");
 679     return revoke.status_code();
 680   } else {
 681     // Thread was not alive.
 682     // Grab Threads_lock before manually trying to revoke bias. This avoids race with a newly
 683     // created JavaThread (that happens to get the same memory address as biaser) synchronizing
 684     // on this object.
 685     {
 686       MutexLocker ml(Threads_lock);
 687       markWord mark = obj->mark();
 688       // Check if somebody else was able to revoke it before biased thread exited.
 689       if (!mark.has_bias_pattern()) {
 690         return NOT_BIASED;
 691       }
 692       ThreadsListHandle tlh;
 693       markWord prototype = obj->klass()->prototype_header();
 694       if (!prototype.has_bias_pattern() || (!tlh.includes(biaser) && biaser == mark.biased_locker() &&
 695                                               prototype.bias_epoch() == mark.bias_epoch())) {
 696         obj->cas_set_mark(markWord::prototype().set_age(mark.age()), mark);
 697         if (event.should_commit()) {
 698           post_revocation_event(&event, obj->klass(), &revoke);
 699         }
 700         assert(!obj->mark().has_bias_pattern(), "bias should be revoked by now");
 701         return BIAS_REVOKED;
 702       }
 703     }
 704   }
 705 
 706   return NOT_REVOKED;
 707 }
 708 
 709 
 710 // Caller should have instantiated a ResourceMark object before calling this method
 711 void BiasedLocking::walk_stack_and_revoke(oop obj, JavaThread* biased_locker) {
 712   assert(!SafepointSynchronize::is_at_safepoint() || !ThreadLocalHandshakes,
 713          "if ThreadLocalHandshakes is enabled this should always be executed outside safepoints");
 714   assert(Thread::current() == biased_locker || Thread::current()->is_VM_thread(), "wrong thread");
 715 


 796       Klass* k = obj->klass();
 797       markWord prototype_header = k->prototype_header();
 798       if (!prototype_header.has_bias_pattern()) {
 799         // This object has a stale bias from before the bulk revocation
 800         // for this data type occurred. It's pointless to update the
 801         // heuristics at this point so simply update the header with a
 802         // CAS. If we fail this race, the object's bias has been revoked
 803         // by another thread so we simply return and let the caller deal
 804         // with it.
 805         obj->cas_set_mark(prototype_header.set_age(mark.age()), mark);
 806         assert(!obj->mark().has_bias_pattern(), "even if we raced, should still be revoked");
 807         return BIAS_REVOKED;
 808       } else if (prototype_header.bias_epoch() != mark.bias_epoch()) {
 809         // The epoch of this biasing has expired indicating that the
 810         // object is effectively unbiased. Depending on whether we need
 811         // to rebias or revoke the bias of this object we can do it
 812         // efficiently enough with a CAS that we shouldn't update the
 813         // heuristics. This is normally done in the assembly code but we
 814         // can reach this point due to various points in the runtime
 815         // needing to revoke biases.
 816         markWord res_mark(0);
 817         if (attempt_rebias) {
 818           assert(THREAD->is_Java_thread(), "");
 819           markWord biased_value       = mark;
 820           markWord rebiased_prototype = markWord::encode((JavaThread*) THREAD, mark.age(), prototype_header.bias_epoch());
 821           res_mark = obj->cas_set_mark(rebiased_prototype, mark);
 822           if (res_mark == biased_value) {
 823             return BIAS_REVOKED_AND_REBIASED;
 824           }
 825         } else {
 826           markWord biased_value       = mark;
 827           markWord unbiased_prototype = markWord::prototype().set_age(mark.age());
 828           res_mark = obj->cas_set_mark(unbiased_prototype, mark);
 829           if (res_mark == biased_value) {
 830             return BIAS_REVOKED;
 831           }
 832         }
 833         mark = res_mark;  // Refresh mark with the latest value.
 834       }
 835     }
 836 




  28 #include "jfr/support/jfrThreadId.hpp"
  29 #include "logging/log.hpp"
  30 #include "memory/resourceArea.hpp"
  31 #include "oops/klass.inline.hpp"
  32 #include "oops/markOop.hpp"
  33 #include "oops/oop.inline.hpp"
  34 #include "runtime/atomic.hpp"
  35 #include "runtime/basicLock.hpp"
  36 #include "runtime/biasedLocking.hpp"
  37 #include "runtime/handles.inline.hpp"
  38 #include "runtime/task.hpp"
  39 #include "runtime/threadSMR.hpp"
  40 #include "runtime/vframe.hpp"
  41 #include "runtime/vmThread.hpp"
  42 #include "runtime/vmOperations.hpp"
  43 
  44 
  45 static bool _biased_locking_enabled = false;
  46 BiasedLockingCounters BiasedLocking::_counters;
  47 
  48 static GrowableArray<Handle>*   _preserved_oop_stack  = NULL;
  49 static GrowableArray<markWord>* _preserved_mark_stack = NULL;
  50 
  51 static void enable_biased_locking(InstanceKlass* k) {
  52   k->set_prototype_header(markWord::biased_locking_prototype());
  53 }
  54 
  55 static void enable_biased_locking() {
  56   _biased_locking_enabled = true;
  57   log_info(biasedlocking)("Biased locking enabled");
  58 }
  59 
  60 class VM_EnableBiasedLocking: public VM_Operation {
  61  public:
  62   VM_EnableBiasedLocking() {}
  63   VMOp_Type type() const          { return VMOp_EnableBiasedLocking; }
  64   Mode evaluation_mode() const    { return _async_safepoint; }
  65   bool is_cheap_allocated() const { return true; }
  66 
  67   void doit() {
  68     // Iterate the class loader data dictionaries enabling biased locking for all


 461           if ((owner->klass() == k_o) && mark.has_bias_pattern()) {
 462             single_revoke_at_safepoint(owner, false, true, requesting_thread, NULL);
 463           }
 464         }
 465       }
 466 
 467       // Must force the bias of the passed object to be forcibly revoked
 468       // as well to ensure guarantees to callers
 469       single_revoke_at_safepoint(o, false, true, requesting_thread, NULL);
 470     }
 471   } // ThreadsListHandle is destroyed here.
 472 
 473   log_info(biasedlocking)("* Ending bulk revocation");
 474 
 475   BiasedLocking::Condition status_code = BIAS_REVOKED;
 476 
 477   if (attempt_rebias_of_object &&
 478       o->mark().has_bias_pattern() &&
 479       klass->prototype_header().has_bias_pattern()) {
 480     markWord new_mark = markWord::encode(requesting_thread, o->mark().age(),
 481                                          klass->prototype_header().bias_epoch());
 482     o->set_mark(new_mark);
 483     status_code = BIAS_REVOKED_AND_REBIASED;
 484     log_info(biasedlocking)("  Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread);
 485   }
 486 
 487   assert(!o->mark().has_bias_pattern() ||
 488          (attempt_rebias_of_object && (o->mark().biased_locker() == requesting_thread)),
 489          "bug in bulk bias revocation");
 490 
 491   return status_code;
 492 }
 493 
 494 
 495 static void clean_up_cached_monitor_info(JavaThread* thread = NULL) {
 496   if (thread != NULL) {
 497     thread->set_cached_monitor_info(NULL);
 498   } else {
 499     // Walk the thread list clearing out the cached monitors
 500     for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
 501       thr->set_cached_monitor_info(NULL);


 675     if (event.should_commit() && revoke.status_code() == BIAS_REVOKED) {
 676       post_revocation_event(&event, obj->klass(), &revoke);
 677     }
 678     assert(!obj->mark().has_bias_pattern(), "invariant");
 679     return revoke.status_code();
 680   } else {
 681     // Thread was not alive.
 682     // Grab Threads_lock before manually trying to revoke bias. This avoids race with a newly
 683     // created JavaThread (that happens to get the same memory address as biaser) synchronizing
 684     // on this object.
 685     {
 686       MutexLocker ml(Threads_lock);
 687       markWord mark = obj->mark();
 688       // Check if somebody else was able to revoke it before biased thread exited.
 689       if (!mark.has_bias_pattern()) {
 690         return NOT_BIASED;
 691       }
 692       ThreadsListHandle tlh;
 693       markWord prototype = obj->klass()->prototype_header();
 694       if (!prototype.has_bias_pattern() || (!tlh.includes(biaser) && biaser == mark.biased_locker() &&
 695                                              prototype.bias_epoch() == mark.bias_epoch())) {
 696         obj->cas_set_mark(markWord::prototype().set_age(mark.age()), mark);
 697         if (event.should_commit()) {
 698           post_revocation_event(&event, obj->klass(), &revoke);
 699         }
 700         assert(!obj->mark().has_bias_pattern(), "bias should be revoked by now");
 701         return BIAS_REVOKED;
 702       }
 703     }
 704   }
 705 
 706   return NOT_REVOKED;
 707 }
 708 
 709 
 710 // Caller should have instantiated a ResourceMark object before calling this method
 711 void BiasedLocking::walk_stack_and_revoke(oop obj, JavaThread* biased_locker) {
 712   assert(!SafepointSynchronize::is_at_safepoint() || !ThreadLocalHandshakes,
 713          "if ThreadLocalHandshakes is enabled this should always be executed outside safepoints");
 714   assert(Thread::current() == biased_locker || Thread::current()->is_VM_thread(), "wrong thread");
 715 


 796       Klass* k = obj->klass();
 797       markWord prototype_header = k->prototype_header();
 798       if (!prototype_header.has_bias_pattern()) {
 799         // This object has a stale bias from before the bulk revocation
 800         // for this data type occurred. It's pointless to update the
 801         // heuristics at this point so simply update the header with a
 802         // CAS. If we fail this race, the object's bias has been revoked
 803         // by another thread so we simply return and let the caller deal
 804         // with it.
 805         obj->cas_set_mark(prototype_header.set_age(mark.age()), mark);
 806         assert(!obj->mark().has_bias_pattern(), "even if we raced, should still be revoked");
 807         return BIAS_REVOKED;
 808       } else if (prototype_header.bias_epoch() != mark.bias_epoch()) {
 809         // The epoch of this biasing has expired indicating that the
 810         // object is effectively unbiased. Depending on whether we need
 811         // to rebias or revoke the bias of this object we can do it
 812         // efficiently enough with a CAS that we shouldn't update the
 813         // heuristics. This is normally done in the assembly code but we
 814         // can reach this point due to various points in the runtime
 815         // needing to revoke biases.
 816         markWord res_mark;
 817         if (attempt_rebias) {
 818           assert(THREAD->is_Java_thread(), "");
 819           markWord biased_value       = mark;
 820           markWord rebiased_prototype = markWord::encode((JavaThread*) THREAD, mark.age(), prototype_header.bias_epoch());
 821           res_mark = obj->cas_set_mark(rebiased_prototype, mark);
 822           if (res_mark == biased_value) {
 823             return BIAS_REVOKED_AND_REBIASED;
 824           }
 825         } else {
 826           markWord biased_value       = mark;
 827           markWord unbiased_prototype = markWord::prototype().set_age(mark.age());
 828           res_mark = obj->cas_set_mark(unbiased_prototype, mark);
 829           if (res_mark == biased_value) {
 830             return BIAS_REVOKED;
 831           }
 832         }
 833         mark = res_mark;  // Refresh mark with the latest value.
 834       }
 835     }
 836 


< prev index next >