692 markWord mark = read_stable_mark(obj); |
692 markWord mark = read_stable_mark(obj); |
693 |
693 |
694 // object should remain ineligible for biased locking |
694 // object should remain ineligible for biased locking |
695 assert(!mark.has_bias_pattern(), "invariant"); |
695 assert(!mark.has_bias_pattern(), "invariant"); |
696 |
696 |
697 if (mark.is_neutral()) { |
697 if (mark.is_neutral()) { // if this is a normal header |
698 hash = mark.hash(); // this is a normal header |
698 hash = mark.hash(); |
699 if (hash != 0) { // if it has hash, just return it |
699 if (hash != 0) { // if it has a hash, just return it |
700 return hash; |
700 return hash; |
701 } |
701 } |
702 hash = get_next_hash(self, obj); // allocate a new hash code |
702 hash = get_next_hash(self, obj); // get a new hash |
703 temp = mark.copy_set_hash(hash); // merge the hash code into header |
703 temp = mark.copy_set_hash(hash); // merge the hash into header |
704 // use (machine word version) atomic operation to install the hash |
704 // try to install the hash |
705 test = obj->cas_set_mark(temp, mark); |
705 test = obj->cas_set_mark(temp, mark); |
706 if (test == mark) { |
706 if (test == mark) { // if the hash was installed, return it |
707 return hash; |
707 return hash; |
708 } |
708 } |
709 // If atomic operation failed, we must inflate the header |
709 // Failed to install the hash. It could be that another thread |
710 // into heavy weight monitor. We could add more code here |
710 // installed the hash just before our attempt or inflation has |
711 // for fast path, but it does not worth the complexity. |
711 // occurred or... so we fall thru to inflate the monitor for |
|
712 // stability and then install the hash. |
712 } else if (mark.has_monitor()) { |
713 } else if (mark.has_monitor()) { |
713 monitor = mark.monitor(); |
714 monitor = mark.monitor(); |
714 temp = monitor->header(); |
715 temp = monitor->header(); |
715 assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); |
716 assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); |
716 hash = temp.hash(); |
717 hash = temp.hash(); |
717 if (hash != 0) { |
718 if (hash != 0) { // if it has a hash, just return it |
718 return hash; |
719 return hash; |
719 } |
720 } |
720 // Skip to the following code to reduce code size |
721 // Fall thru so we only have one place that installs the hash in |
|
722 // the ObjectMonitor. |
721 } else if (self->is_lock_owned((address)mark.locker())) { |
723 } else if (self->is_lock_owned((address)mark.locker())) { |
722 temp = mark.displaced_mark_helper(); // this is a lightweight monitor owned |
724 // This is a stack lock owned by the calling thread so fetch the |
|
725 // displaced markWord from the BasicLock on the stack. |
|
726 temp = mark.displaced_mark_helper(); |
723 assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); |
727 assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); |
724 hash = temp.hash(); // by current thread, check if the displaced |
728 hash = temp.hash(); |
725 if (hash != 0) { // header contains hash code |
729 if (hash != 0) { // if it has a hash, just return it |
726 return hash; |
730 return hash; |
727 } |
731 } |
728 // WARNING: |
732 // WARNING: |
729 // The displaced header in the BasicLock on a thread's stack |
733 // The displaced header in the BasicLock on a thread's stack |
730 // is strictly immutable. It CANNOT be changed in ANY cases. |
734 // is strictly immutable. It CANNOT be changed in ANY cases. |
733 // a thread's stack can be asynchronously read by other threads |
737 // a thread's stack can be asynchronously read by other threads |
734 // during an inflate() call so any change to that stack memory |
738 // during an inflate() call so any change to that stack memory |
735 // may not propagate to other threads correctly. |
739 // may not propagate to other threads correctly. |
736 } |
740 } |
737 |
741 |
738 // Inflate the monitor to set hash code |
742 // Inflate the monitor to set the hash. |
739 monitor = inflate(self, obj, inflate_cause_hash_code); |
743 monitor = inflate(self, obj, inflate_cause_hash_code); |
740 // Load displaced header and check it has hash code |
744 // Load ObjectMonitor's header/dmw field and see if it has a hash. |
741 mark = monitor->header(); |
745 mark = monitor->header(); |
742 assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); |
746 assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); |
743 hash = mark.hash(); |
747 hash = mark.hash(); |
744 if (hash == 0) { |
748 if (hash == 0) { // if it does not have a hash |
745 hash = get_next_hash(self, obj); |
749 hash = get_next_hash(self, obj); // get a new hash |
746 temp = mark.copy_set_hash(hash); // merge hash code into header |
750 temp = mark.copy_set_hash(hash); // merge the hash into header |
747 assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); |
751 assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); |
748 uintptr_t v = Atomic::cmpxchg(temp.value(), (volatile uintptr_t*)monitor->header_addr(), mark.value()); |
752 uintptr_t v = Atomic::cmpxchg(temp.value(), (volatile uintptr_t*)monitor->header_addr(), mark.value()); |
749 test = markWord(v); |
753 test = markWord(v); |
750 if (test != mark) { |
754 if (test != mark) { |
751 // The only non-deflation update to the ObjectMonitor's |
755 // The attempt to update the ObjectMonitor's header/dmw field |
752 // header/dmw field is to merge in the hash code. If someone |
756 // did not work. This can happen if another thread managed to |
753 // adds a new usage of the header/dmw field, please update |
757 // merge in the hash just before our cmpxchg(). |
754 // this code. |
758 // If we add any new usages of the header/dmw field, this code |
|
759 // will need to be updated. |
755 hash = test.hash(); |
760 hash = test.hash(); |
756 assert(test.is_neutral(), "invariant: header=" INTPTR_FORMAT, test.value()); |
761 assert(test.is_neutral(), "invariant: header=" INTPTR_FORMAT, test.value()); |
757 assert(hash != 0, "Trivial unexpected object/monitor header usage."); |
762 assert(hash != 0, "should only have lost the race to a thread that set a non-zero hash"); |
758 } |
763 } |
759 } |
764 } |
760 // We finally get the hash |
765 // We finally get the hash. |
761 return hash; |
766 return hash; |
762 } |
767 } |
763 |
768 |
764 // Deprecated -- use FastHashCode() instead. |
769 // Deprecated -- use FastHashCode() instead. |
765 |
770 |