src/hotspot/share/runtime/synchronizer.cpp
changeset 59225 80e1201f6c9a
parent 59156 14fa9e70ae71
child 59247 56bf71d64d51
equal deleted inserted replaced
59224:55fdee124e89 59225:80e1201f6c9a
   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