< prev index next >

src/hotspot/share/runtime/biasedLocking.cpp

Print this page

        

*** 155,165 **** } // 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). ! BiasedLocking::Condition BiasedLocking::single_revoke_at_safepoint(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread, JavaThread** biased_locker) { assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint"); assert(Thread::current()->is_VM_thread(), "must be VMThread"); markWord mark = obj->mark(); if (!mark.has_bias_pattern()) { --- 155,165 ---- } // 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). ! void BiasedLocking::single_revoke_at_safepoint(oop obj, bool is_bulk, JavaThread* requesting_thread, JavaThread** biased_locker) { assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint"); assert(Thread::current()->is_VM_thread(), "must be VMThread"); markWord mark = obj->mark(); if (!mark.has_bias_pattern()) {
*** 171,227 **** " because it's no longer biased)", p2i((void *)obj), mark.value(), obj->klass()->external_name(), (intptr_t) requesting_thread); } ! return NOT_BIASED; } uint age = mark.age(); - markWord biased_prototype = markWord::biased_locking_prototype().set_age(age); markWord unbiased_prototype = markWord::prototype().set_age(age); // Log at "info" level if not bulk, else "trace" level if (!is_bulk) { ResourceMark rm; log_info(biasedlocking)("Revoking bias of object " INTPTR_FORMAT ", mark " INTPTR_FORMAT ", type %s, prototype header " INTPTR_FORMAT ! ", allow rebias %d, requesting thread " INTPTR_FORMAT, p2i((void *)obj), mark.value(), obj->klass()->external_name(), obj->klass()->prototype_header().value(), - (allow_rebias ? 1 : 0), (intptr_t) requesting_thread); } else { ResourceMark rm; log_trace(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT ! " , allow rebias %d , requesting thread " INTPTR_FORMAT, p2i((void *)obj), mark.value(), obj->klass()->external_name(), obj->klass()->prototype_header().value(), - (allow_rebias ? 1 : 0), (intptr_t) requesting_thread); } JavaThread* biased_thread = mark.biased_locker(); if (biased_thread == NULL) { // Object is anonymously biased. We can get here if, for // example, we revoke the bias due to an identity hash code // being computed for an object. - if (!allow_rebias) { obj->set_mark(unbiased_prototype); ! } // Log at "info" level if not bulk, else "trace" level if (!is_bulk) { log_info(biasedlocking)(" Revoked bias of anonymously-biased object"); } else { log_trace(biasedlocking)(" Revoked bias of anonymously-biased object"); } ! return BIAS_REVOKED; } // Handle case where the thread toward which the object was biased has exited bool thread_is_alive = false; if (requesting_thread == biased_thread) { --- 171,223 ---- " because it's no longer biased)", p2i((void *)obj), mark.value(), obj->klass()->external_name(), (intptr_t) requesting_thread); } ! return; } uint age = mark.age(); markWord unbiased_prototype = markWord::prototype().set_age(age); // Log at "info" level if not bulk, else "trace" level if (!is_bulk) { ResourceMark rm; log_info(biasedlocking)("Revoking bias of object " INTPTR_FORMAT ", mark " INTPTR_FORMAT ", type %s, prototype header " INTPTR_FORMAT ! ", requesting thread " INTPTR_FORMAT, p2i((void *)obj), mark.value(), obj->klass()->external_name(), obj->klass()->prototype_header().value(), (intptr_t) requesting_thread); } else { ResourceMark rm; log_trace(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT ! " , requesting thread " INTPTR_FORMAT, p2i((void *)obj), mark.value(), obj->klass()->external_name(), obj->klass()->prototype_header().value(), (intptr_t) requesting_thread); } JavaThread* biased_thread = mark.biased_locker(); if (biased_thread == NULL) { // Object is anonymously biased. We can get here if, for // example, we revoke the bias due to an identity hash code // being computed for an object. obj->set_mark(unbiased_prototype); ! // Log at "info" level if not bulk, else "trace" level if (!is_bulk) { log_info(biasedlocking)(" Revoked bias of anonymously-biased object"); } else { log_trace(biasedlocking)(" Revoked bias of anonymously-biased object"); } ! return; } // Handle case where the thread toward which the object was biased has exited bool thread_is_alive = false; if (requesting_thread == biased_thread) {
*** 229,252 **** } else { ThreadsListHandle tlh; thread_is_alive = tlh.includes(biased_thread); } if (!thread_is_alive) { - if (allow_rebias) { - obj->set_mark(biased_prototype); - } else { obj->set_mark(unbiased_prototype); - } // Log at "info" level if not bulk, else "trace" level if (!is_bulk) { log_info(biasedlocking)(" Revoked bias of object biased toward dead thread (" PTR_FORMAT ")", p2i(biased_thread)); } else { log_trace(biasedlocking)(" Revoked bias of object biased toward dead thread (" PTR_FORMAT ")", p2i(biased_thread)); } ! return BIAS_REVOKED; } // Log at "info" level if not bulk, else "trace" level if (!is_bulk) { log_info(biasedlocking)(" Revoked bias of object biased toward live thread (" --- 225,244 ---- } else { ThreadsListHandle tlh; thread_is_alive = tlh.includes(biased_thread); } if (!thread_is_alive) { obj->set_mark(unbiased_prototype); // Log at "info" level if not bulk, else "trace" level if (!is_bulk) { log_info(biasedlocking)(" Revoked bias of object biased toward dead thread (" PTR_FORMAT ")", p2i(biased_thread)); } else { log_trace(biasedlocking)(" Revoked bias of object biased toward dead thread (" PTR_FORMAT ")", p2i(biased_thread)); } ! return; } // Log at "info" level if not bulk, else "trace" level if (!is_bulk) { log_info(biasedlocking)(" Revoked bias of object biased toward live thread ("
*** 299,322 **** if (!is_bulk) { log_info(biasedlocking)(" Revoked bias of currently-unlocked object"); } else { log_trace(biasedlocking)(" Revoked bias of currently-unlocked object"); } - if (allow_rebias) { - obj->set_mark(biased_prototype); - } else { // Store the unlocked value into the object's header. obj->set_mark(unbiased_prototype); } - } // If requested, return information on which thread held the bias if (biased_locker != NULL) { *biased_locker = biased_thread; } - - return BIAS_REVOKED; } enum HeuristicsResult { HR_NOT_BIASED = 1, --- 291,308 ----
*** 377,390 **** return HR_SINGLE_REVOKE; } ! BiasedLocking::Condition BiasedLocking::bulk_revoke_or_rebias_at_safepoint(oop o, ! bool bulk_rebias, ! bool attempt_rebias_of_object, ! JavaThread* requesting_thread) { assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint"); assert(Thread::current()->is_VM_thread(), "must be VMThread"); log_info(biasedlocking)("* Beginning bulk revocation (kind == %s) because of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", --- 363,373 ---- return HR_SINGLE_REVOKE; } ! void BiasedLocking::bulk_revoke_at_safepoint(oop o, bool bulk_rebias, JavaThread* requesting_thread) { assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint"); assert(Thread::current()->is_VM_thread(), "must be VMThread"); log_info(biasedlocking)("* Beginning bulk revocation (kind == %s) because of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
*** 435,445 **** } } // At this point we're done. All we have to do is potentially // adjust the header of the given object to revoke its bias. ! single_revoke_at_safepoint(o, attempt_rebias_of_object && klass->prototype_header().has_bias_pattern(), true, requesting_thread, NULL); } else { if (log_is_enabled(Info, biasedlocking)) { ResourceMark rm; log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); } --- 418,428 ---- } } // At this point we're done. All we have to do is potentially // adjust the header of the given object to revoke its bias. ! single_revoke_at_safepoint(o, true, requesting_thread, NULL); } else { if (log_is_enabled(Info, biasedlocking)) { ResourceMark rm; log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); }
*** 457,496 **** for (int i = 0; i < cached_monitor_info->length(); i++) { MonitorInfo* mon_info = cached_monitor_info->at(i); oop owner = mon_info->owner(); markWord mark = owner->mark(); if ((owner->klass() == k_o) && mark.has_bias_pattern()) { ! single_revoke_at_safepoint(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 ! single_revoke_at_safepoint(o, false, true, requesting_thread, NULL); } } // ThreadsListHandle is destroyed here. log_info(biasedlocking)("* Ending bulk revocation"); ! BiasedLocking::Condition status_code = BIAS_REVOKED; ! ! if (attempt_rebias_of_object && ! o->mark().has_bias_pattern() && ! klass->prototype_header().has_bias_pattern()) { ! markWord new_mark = markWord::encode(requesting_thread, o->mark().age(), ! klass->prototype_header().bias_epoch()); ! o->set_mark(new_mark); ! status_code = BIAS_REVOKED_AND_REBIASED; ! log_info(biasedlocking)(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread); ! } ! ! assert(!o->mark().has_bias_pattern() || ! (attempt_rebias_of_object && (o->mark().biased_locker() == requesting_thread)), ! "bug in bulk bias revocation"); ! ! return status_code; } static void clean_up_cached_monitor_info(JavaThread* thread = NULL) { if (thread != NULL) { --- 440,463 ---- for (int i = 0; i < cached_monitor_info->length(); i++) { MonitorInfo* mon_info = cached_monitor_info->at(i); oop owner = mon_info->owner(); markWord mark = owner->mark(); if ((owner->klass() == k_o) && mark.has_bias_pattern()) { ! single_revoke_at_safepoint(owner, true, requesting_thread, NULL); } } } // Must force the bias of the passed object to be forcibly revoked // as well to ensure guarantees to callers ! single_revoke_at_safepoint(o, true, requesting_thread, NULL); } } // ThreadsListHandle is destroyed here. log_info(biasedlocking)("* Ending bulk revocation"); ! assert(!o->mark().has_bias_pattern(), "bug in bulk bias revocation"); } static void clean_up_cached_monitor_info(JavaThread* thread = NULL) { if (thread != NULL) {
*** 507,547 **** class VM_BulkRevokeBias : public VM_Operation { private: Handle* _obj; JavaThread* _requesting_thread; bool _bulk_rebias; - bool _attempt_rebias_of_object; - BiasedLocking::Condition _status_code; uint64_t _safepoint_id; public: VM_BulkRevokeBias(Handle* obj, JavaThread* requesting_thread, ! bool bulk_rebias, ! bool attempt_rebias_of_object) : _obj(obj) , _requesting_thread(requesting_thread) , _bulk_rebias(bulk_rebias) - , _attempt_rebias_of_object(attempt_rebias_of_object) - , _status_code(BiasedLocking::NOT_BIASED) , _safepoint_id(0) {} virtual VMOp_Type type() const { return VMOp_BulkRevokeBias; } virtual void doit() { ! _status_code = BiasedLocking::bulk_revoke_or_rebias_at_safepoint((*_obj)(), _bulk_rebias, _attempt_rebias_of_object, _requesting_thread); _safepoint_id = SafepointSynchronize::safepoint_id(); clean_up_cached_monitor_info(); } bool is_bulk_rebias() const { return _bulk_rebias; } - BiasedLocking::Condition status_code() const { - return _status_code; - } - uint64_t safepoint_id() const { return _safepoint_id; } }; --- 474,505 ---- class VM_BulkRevokeBias : public VM_Operation { private: Handle* _obj; JavaThread* _requesting_thread; bool _bulk_rebias; uint64_t _safepoint_id; public: VM_BulkRevokeBias(Handle* obj, JavaThread* requesting_thread, ! bool bulk_rebias) : _obj(obj) , _requesting_thread(requesting_thread) , _bulk_rebias(bulk_rebias) , _safepoint_id(0) {} virtual VMOp_Type type() const { return VMOp_BulkRevokeBias; } virtual void doit() { ! BiasedLocking::bulk_revoke_at_safepoint((*_obj)(), _bulk_rebias, _requesting_thread); _safepoint_id = SafepointSynchronize::safepoint_id(); clean_up_cached_monitor_info(); } bool is_bulk_rebias() const { return _bulk_rebias; } uint64_t safepoint_id() const { return _safepoint_id; } };
*** 767,800 **** assert(!obj->mark().has_bias_pattern(), "must not be biased"); } ! BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) { assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint"); while (true) { // We can revoke the biases of anonymously-biased objects // efficiently enough that we should not cause these revocations to // update the heuristics because doing so may cause unwanted bulk // revocations (which are expensive) to occur. markWord mark = obj->mark(); ! if (mark.is_biased_anonymously() && !attempt_rebias) { // We are probably trying to revoke the bias of this object due to // an identity hash code computation. Try to revoke the bias // without a safepoint. This is possible if we can successfully // compare-and-exchange an unbiased header into the mark word of // the object, meaning that no other thread has raced to acquire // the bias of the object. markWord biased_value = mark; markWord unbiased_prototype = markWord::prototype().set_age(mark.age()); markWord res_mark = obj->cas_set_mark(unbiased_prototype, mark); if (res_mark == biased_value) { ! return BIAS_REVOKED; } mark = res_mark; // Refresh mark with the latest value. ! } else if (mark.has_bias_pattern()) { Klass* k = obj->klass(); markWord prototype_header = k->prototype_header(); if (!prototype_header.has_bias_pattern()) { // This object has a stale bias from before the bulk revocation // for this data type occurred. It's pointless to update the --- 725,763 ---- assert(!obj->mark().has_bias_pattern(), "must not be biased"); } ! void BiasedLocking::revoke(Handle obj, TRAPS) { assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint"); while (true) { // We can revoke the biases of anonymously-biased objects // efficiently enough that we should not cause these revocations to // update the heuristics because doing so may cause unwanted bulk // revocations (which are expensive) to occur. markWord mark = obj->mark(); ! ! if (!mark.has_bias_pattern()) { ! return; ! } ! ! if (mark.is_biased_anonymously()) { // We are probably trying to revoke the bias of this object due to // an identity hash code computation. Try to revoke the bias // without a safepoint. This is possible if we can successfully // compare-and-exchange an unbiased header into the mark word of // the object, meaning that no other thread has raced to acquire // the bias of the object. markWord biased_value = mark; markWord unbiased_prototype = markWord::prototype().set_age(mark.age()); markWord res_mark = obj->cas_set_mark(unbiased_prototype, mark); if (res_mark == biased_value) { ! return; } mark = res_mark; // Refresh mark with the latest value. ! } else { Klass* k = obj->klass(); markWord prototype_header = k->prototype_header(); if (!prototype_header.has_bias_pattern()) { // This object has a stale bias from before the bulk revocation // for this data type occurred. It's pointless to update the
*** 802,844 **** // CAS. If we fail this race, the object's bias has been revoked // by another thread so we simply return and let the caller deal // with it. obj->cas_set_mark(prototype_header.set_age(mark.age()), mark); assert(!obj->mark().has_bias_pattern(), "even if we raced, should still be revoked"); ! return BIAS_REVOKED; } else if (prototype_header.bias_epoch() != mark.bias_epoch()) { // The epoch of this biasing has expired indicating that the ! // object is effectively unbiased. Depending on whether we need ! // to rebias or revoke the bias of this object we can do it ! // efficiently enough with a CAS that we shouldn't update the // heuristics. This is normally done in the assembly code but we // can reach this point due to various points in the runtime // needing to revoke biases. markWord res_mark; - if (attempt_rebias) { - assert(THREAD->is_Java_thread(), ""); - markWord biased_value = mark; - markWord rebiased_prototype = markWord::encode((JavaThread*) THREAD, mark.age(), prototype_header.bias_epoch()); - res_mark = obj->cas_set_mark(rebiased_prototype, mark); - if (res_mark == biased_value) { - return BIAS_REVOKED_AND_REBIASED; - } - } else { markWord biased_value = mark; markWord unbiased_prototype = markWord::prototype().set_age(mark.age()); res_mark = obj->cas_set_mark(unbiased_prototype, mark); if (res_mark == biased_value) { ! return BIAS_REVOKED; ! } } mark = res_mark; // Refresh mark with the latest value. } } HeuristicsResult heuristics = update_heuristics(obj()); if (heuristics == HR_NOT_BIASED) { ! return NOT_BIASED; } else if (heuristics == HR_SINGLE_REVOKE) { JavaThread *blt = mark.biased_locker(); assert(blt != NULL, "invariant"); if (blt == THREAD) { // A thread is trying to revoke the bias of an object biased --- 765,796 ---- // CAS. If we fail this race, the object's bias has been revoked // by another thread so we simply return and let the caller deal // with it. obj->cas_set_mark(prototype_header.set_age(mark.age()), mark); assert(!obj->mark().has_bias_pattern(), "even if we raced, should still be revoked"); ! return; } else if (prototype_header.bias_epoch() != mark.bias_epoch()) { // The epoch of this biasing has expired indicating that the ! // object is effectively unbiased. We can revoke the bias of this ! // object efficiently enough with a CAS that we shouldn't update the // heuristics. This is normally done in the assembly code but we // can reach this point due to various points in the runtime // needing to revoke biases. markWord res_mark; markWord biased_value = mark; markWord unbiased_prototype = markWord::prototype().set_age(mark.age()); res_mark = obj->cas_set_mark(unbiased_prototype, mark); if (res_mark == biased_value) { ! return; } mark = res_mark; // Refresh mark with the latest value. } } HeuristicsResult heuristics = update_heuristics(obj()); if (heuristics == HR_NOT_BIASED) { ! return; } else if (heuristics == HR_SINGLE_REVOKE) { JavaThread *blt = mark.biased_locker(); assert(blt != NULL, "invariant"); if (blt == THREAD) { // A thread is trying to revoke the bias of an object biased
*** 853,881 **** blt->set_cached_monitor_info(NULL); assert(!obj->mark().has_bias_pattern(), "invariant"); if (event.should_commit()) { post_self_revocation_event(&event, obj->klass()); } ! return BIAS_REVOKED; } else { BiasedLocking::Condition cond = single_revoke_with_handshake(obj, (JavaThread*)THREAD, blt); if (cond != NOT_REVOKED) { ! return cond; } } } else { 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()) { post_class_revocation_event(&event, obj->klass(), &bulk_revoke); } ! return bulk_revoke.status_code(); } } } // All objects in objs should be locked by biaser --- 805,832 ---- blt->set_cached_monitor_info(NULL); assert(!obj->mark().has_bias_pattern(), "invariant"); if (event.should_commit()) { post_self_revocation_event(&event, obj->klass()); } ! return; } else { BiasedLocking::Condition cond = single_revoke_with_handshake(obj, (JavaThread*)THREAD, blt); if (cond != NOT_REVOKED) { ! return; } } } else { assert((heuristics == HR_BULK_REVOKE) || (heuristics == HR_BULK_REBIAS), "?"); EventBiasedLockClassRevocation event; VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*)THREAD, ! (heuristics == HR_BULK_REBIAS)); VMThread::execute(&bulk_revoke); if (event.should_commit()) { post_class_revocation_event(&event, obj->klass(), &bulk_revoke); } ! return; } } } // All objects in objs should be locked by biaser
*** 899,915 **** assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint"); oop obj = h_obj(); HeuristicsResult heuristics = update_heuristics(obj); if (heuristics == HR_SINGLE_REVOKE) { JavaThread* biased_locker = NULL; ! single_revoke_at_safepoint(obj, false, false, NULL, &biased_locker); if (biased_locker) { clean_up_cached_monitor_info(biased_locker); } } 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(); } } --- 850,866 ---- assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint"); oop obj = h_obj(); HeuristicsResult heuristics = update_heuristics(obj); if (heuristics == HR_SINGLE_REVOKE) { JavaThread* biased_locker = NULL; ! single_revoke_at_safepoint(obj, false, NULL, &biased_locker); if (biased_locker) { clean_up_cached_monitor_info(biased_locker); } } else if ((heuristics == HR_BULK_REBIAS) || (heuristics == HR_BULK_REVOKE)) { ! bulk_revoke_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), NULL); clean_up_cached_monitor_info(); } }
*** 918,931 **** int len = objs->length(); for (int i = 0; i < len; i++) { oop obj = (objs->at(i))(); HeuristicsResult heuristics = update_heuristics(obj); if (heuristics == HR_SINGLE_REVOKE) { ! single_revoke_at_safepoint(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(); } --- 869,882 ---- int len = objs->length(); for (int i = 0; i < len; i++) { oop obj = (objs->at(i))(); HeuristicsResult heuristics = update_heuristics(obj); if (heuristics == HR_SINGLE_REVOKE) { ! single_revoke_at_safepoint(obj, false, NULL, NULL); } else if ((heuristics == HR_BULK_REBIAS) || (heuristics == HR_BULK_REVOKE)) { ! bulk_revoke_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), NULL); } } clean_up_cached_monitor_info(); }
< prev index next >