143 |
143 |
144 thread->set_cached_monitor_info(info); |
144 thread->set_cached_monitor_info(info); |
145 return info; |
145 return info; |
146 } |
146 } |
147 |
147 |
148 static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) { |
148 // After the call, *biased_locker will be set to obj->mark()->biased_locker() if biased_locker != NULL, |
|
149 // AND it is a living thread. Otherwise it will not be updated, (i.e. the caller is responsible for initialization). |
|
150 static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread, JavaThread** biased_locker) { |
149 markOop mark = obj->mark(); |
151 markOop mark = obj->mark(); |
150 if (!mark->has_bias_pattern()) { |
152 if (!mark->has_bias_pattern()) { |
151 if (log_is_enabled(Info, biasedlocking)) { |
153 if (log_is_enabled(Info, biasedlocking)) { |
152 ResourceMark rm; |
154 ResourceMark rm; |
153 log_info(biasedlocking)(" (Skipping revocation of object " INTPTR_FORMAT |
155 log_info(biasedlocking)(" (Skipping revocation of object " INTPTR_FORMAT |
294 obj->set_mark(biased_prototype); |
296 obj->set_mark(biased_prototype); |
295 } else { |
297 } else { |
296 // Store the unlocked value into the object's header. |
298 // Store the unlocked value into the object's header. |
297 obj->set_mark(unbiased_prototype); |
299 obj->set_mark(unbiased_prototype); |
298 } |
300 } |
|
301 } |
|
302 |
|
303 // If requested, return information on which thread held the bias |
|
304 if (biased_locker != NULL) { |
|
305 *biased_locker = biased_thread; |
299 } |
306 } |
300 |
307 |
301 return BiasedLocking::BIAS_REVOKED; |
308 return BiasedLocking::BIAS_REVOKED; |
302 } |
309 } |
303 |
310 |
416 } |
423 } |
417 } |
424 } |
418 |
425 |
419 // At this point we're done. All we have to do is potentially |
426 // At this point we're done. All we have to do is potentially |
420 // adjust the header of the given object to revoke its bias. |
427 // adjust the header of the given object to revoke its bias. |
421 revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread); |
428 revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL); |
422 } else { |
429 } else { |
423 if (log_is_enabled(Info, biasedlocking)) { |
430 if (log_is_enabled(Info, biasedlocking)) { |
424 ResourceMark rm; |
431 ResourceMark rm; |
425 log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); |
432 log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); |
426 } |
433 } |
438 for (int i = 0; i < cached_monitor_info->length(); i++) { |
445 for (int i = 0; i < cached_monitor_info->length(); i++) { |
439 MonitorInfo* mon_info = cached_monitor_info->at(i); |
446 MonitorInfo* mon_info = cached_monitor_info->at(i); |
440 oop owner = mon_info->owner(); |
447 oop owner = mon_info->owner(); |
441 markOop mark = owner->mark(); |
448 markOop mark = owner->mark(); |
442 if ((owner->klass() == k_o) && mark->has_bias_pattern()) { |
449 if ((owner->klass() == k_o) && mark->has_bias_pattern()) { |
443 revoke_bias(owner, false, true, requesting_thread); |
450 revoke_bias(owner, false, true, requesting_thread, NULL); |
444 } |
451 } |
445 } |
452 } |
446 } |
453 } |
447 |
454 |
448 // Must force the bias of the passed object to be forcibly revoked |
455 // Must force the bias of the passed object to be forcibly revoked |
449 // as well to ensure guarantees to callers |
456 // as well to ensure guarantees to callers |
450 revoke_bias(o, false, true, requesting_thread); |
457 revoke_bias(o, false, true, requesting_thread, NULL); |
451 } |
458 } |
452 |
459 |
453 log_info(biasedlocking)("* Ending bulk revocation"); |
460 log_info(biasedlocking)("* Ending bulk revocation"); |
454 |
461 |
455 BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED; |
462 BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED; |
484 protected: |
491 protected: |
485 Handle* _obj; |
492 Handle* _obj; |
486 GrowableArray<Handle>* _objs; |
493 GrowableArray<Handle>* _objs; |
487 JavaThread* _requesting_thread; |
494 JavaThread* _requesting_thread; |
488 BiasedLocking::Condition _status_code; |
495 BiasedLocking::Condition _status_code; |
|
496 traceid _biased_locker_id; |
489 |
497 |
490 public: |
498 public: |
491 VM_RevokeBias(Handle* obj, JavaThread* requesting_thread) |
499 VM_RevokeBias(Handle* obj, JavaThread* requesting_thread) |
492 : _obj(obj) |
500 : _obj(obj) |
493 , _objs(NULL) |
501 , _objs(NULL) |
494 , _requesting_thread(requesting_thread) |
502 , _requesting_thread(requesting_thread) |
495 , _status_code(BiasedLocking::NOT_BIASED) {} |
503 , _status_code(BiasedLocking::NOT_BIASED) |
|
504 , _biased_locker_id(0) {} |
496 |
505 |
497 VM_RevokeBias(GrowableArray<Handle>* objs, JavaThread* requesting_thread) |
506 VM_RevokeBias(GrowableArray<Handle>* objs, JavaThread* requesting_thread) |
498 : _obj(NULL) |
507 : _obj(NULL) |
499 , _objs(objs) |
508 , _objs(objs) |
500 , _requesting_thread(requesting_thread) |
509 , _requesting_thread(requesting_thread) |
501 , _status_code(BiasedLocking::NOT_BIASED) {} |
510 , _status_code(BiasedLocking::NOT_BIASED) |
|
511 , _biased_locker_id(0) {} |
502 |
512 |
503 virtual VMOp_Type type() const { return VMOp_RevokeBias; } |
513 virtual VMOp_Type type() const { return VMOp_RevokeBias; } |
504 |
514 |
505 virtual bool doit_prologue() { |
515 virtual bool doit_prologue() { |
506 // Verify that there is actual work to do since the callers just |
516 // Verify that there is actual work to do since the callers just |
523 } |
533 } |
524 |
534 |
525 virtual void doit() { |
535 virtual void doit() { |
526 if (_obj != NULL) { |
536 if (_obj != NULL) { |
527 log_info(biasedlocking)("Revoking bias with potentially per-thread safepoint:"); |
537 log_info(biasedlocking)("Revoking bias with potentially per-thread safepoint:"); |
528 _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread); |
538 JavaThread* biased_locker = NULL; |
|
539 _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread, &biased_locker); |
|
540 if (biased_locker != NULL) { |
|
541 _biased_locker_id = THREAD_TRACE_ID(biased_locker); |
|
542 } |
529 clean_up_cached_monitor_info(); |
543 clean_up_cached_monitor_info(); |
530 return; |
544 return; |
531 } else { |
545 } else { |
532 log_info(biasedlocking)("Revoking bias with global safepoint:"); |
546 log_info(biasedlocking)("Revoking bias with global safepoint:"); |
533 BiasedLocking::revoke_at_safepoint(_objs); |
547 BiasedLocking::revoke_at_safepoint(_objs); |
534 } |
548 } |
535 } |
549 } |
536 |
550 |
537 BiasedLocking::Condition status_code() const { |
551 BiasedLocking::Condition status_code() const { |
538 return _status_code; |
552 return _status_code; |
|
553 } |
|
554 |
|
555 traceid biased_locker() const { |
|
556 return _biased_locker_id; |
539 } |
557 } |
540 }; |
558 }; |
541 |
559 |
542 |
560 |
543 class VM_BulkRevokeBias : public VM_RevokeBias { |
561 class VM_BulkRevokeBias : public VM_RevokeBias { |
643 // can come in with a CAS to steal the bias of an object that has a |
661 // can come in with a CAS to steal the bias of an object that has a |
644 // stale epoch. |
662 // stale epoch. |
645 ResourceMark rm; |
663 ResourceMark rm; |
646 log_info(biasedlocking)("Revoking bias by walking my own stack:"); |
664 log_info(biasedlocking)("Revoking bias by walking my own stack:"); |
647 EventBiasedLockSelfRevocation event; |
665 EventBiasedLockSelfRevocation event; |
648 BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD); |
666 BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD, NULL); |
649 ((JavaThread*) THREAD)->set_cached_monitor_info(NULL); |
667 ((JavaThread*) THREAD)->set_cached_monitor_info(NULL); |
650 assert(cond == BIAS_REVOKED, "why not?"); |
668 assert(cond == BIAS_REVOKED, "why not?"); |
651 if (event.should_commit()) { |
669 if (event.should_commit()) { |
652 event.set_lockClass(k); |
670 event.set_lockClass(k); |
653 event.commit(); |
671 event.commit(); |
659 VMThread::execute(&revoke); |
677 VMThread::execute(&revoke); |
660 if (event.should_commit() && (revoke.status_code() != NOT_BIASED)) { |
678 if (event.should_commit() && (revoke.status_code() != NOT_BIASED)) { |
661 event.set_lockClass(k); |
679 event.set_lockClass(k); |
662 // Subtract 1 to match the id of events committed inside the safepoint |
680 // Subtract 1 to match the id of events committed inside the safepoint |
663 event.set_safepointId(SafepointSynchronize::safepoint_counter() - 1); |
681 event.set_safepointId(SafepointSynchronize::safepoint_counter() - 1); |
|
682 event.set_previousOwner(revoke.biased_locker()); |
664 event.commit(); |
683 event.commit(); |
665 } |
684 } |
666 return revoke.status_code(); |
685 return revoke.status_code(); |
667 } |
686 } |
668 } |
687 } |
698 void BiasedLocking::revoke_at_safepoint(Handle h_obj) { |
717 void BiasedLocking::revoke_at_safepoint(Handle h_obj) { |
699 assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint"); |
718 assert(SafepointSynchronize::is_at_safepoint(), "must only be called while at safepoint"); |
700 oop obj = h_obj(); |
719 oop obj = h_obj(); |
701 HeuristicsResult heuristics = update_heuristics(obj, false); |
720 HeuristicsResult heuristics = update_heuristics(obj, false); |
702 if (heuristics == HR_SINGLE_REVOKE) { |
721 if (heuristics == HR_SINGLE_REVOKE) { |
703 revoke_bias(obj, false, false, NULL); |
722 revoke_bias(obj, false, false, NULL, NULL); |
704 } else if ((heuristics == HR_BULK_REBIAS) || |
723 } else if ((heuristics == HR_BULK_REBIAS) || |
705 (heuristics == HR_BULK_REVOKE)) { |
724 (heuristics == HR_BULK_REVOKE)) { |
706 bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL); |
725 bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL); |
707 } |
726 } |
708 clean_up_cached_monitor_info(); |
727 clean_up_cached_monitor_info(); |
714 int len = objs->length(); |
733 int len = objs->length(); |
715 for (int i = 0; i < len; i++) { |
734 for (int i = 0; i < len; i++) { |
716 oop obj = (objs->at(i))(); |
735 oop obj = (objs->at(i))(); |
717 HeuristicsResult heuristics = update_heuristics(obj, false); |
736 HeuristicsResult heuristics = update_heuristics(obj, false); |
718 if (heuristics == HR_SINGLE_REVOKE) { |
737 if (heuristics == HR_SINGLE_REVOKE) { |
719 revoke_bias(obj, false, false, NULL); |
738 revoke_bias(obj, false, false, NULL, NULL); |
720 } else if ((heuristics == HR_BULK_REBIAS) || |
739 } else if ((heuristics == HR_BULK_REBIAS) || |
721 (heuristics == HR_BULK_REVOKE)) { |
740 (heuristics == HR_BULK_REVOKE)) { |
722 bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL); |
741 bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL); |
723 } |
742 } |
724 } |
743 } |