hashCode--C++源码

intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {

  if (UseBiasedLocking) {

    // NOTE: many places throughout the JVM do not expect a safepoint

    // to be taken here, in particular most operations on perm gen

    // objects. However, we only ever bias Java instances and all of

    // the call sites of identity_hash that might revoke biases have

    // been checked to make sure they can handle a safepoint. The

    // added check of the bias pattern is to avoid useless calls to

    // thread-local storage.

    if (obj->mark()->has_bias_pattern()) {

      // Box and unbox the raw reference just in case we cause a STW safepoint.

      Handle hobj (Self, obj) ;         

      // Relaxing assertion for bug 6320749.

      assert (Universe::verify_in_progress() ||

          !SafepointSynchronize::is_at_safepoint(),

         "biases should not be seen by VM thread here");

      BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());

      obj = hobj() ; 

      assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");

    }

  }

 

  // hashCode() is a heap mutator ...

  // Relaxing assertion for bug 6320749.

  assert (Universe::verify_in_progress() ||

      !SafepointSynchronize::is_at_safepoint(), "invariant") ; 

  assert (Universe::verify_in_progress() ||

      Self->is_Java_thread() , "invariant") ; 

  assert (Universe::verify_in_progress() ||

     ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;

 

  ObjectMonitor* monitor = NULL;

  markOop temp, test;

  intptr_t hash;

  markOop mark = ReadStableMark (obj);

 

  // object should remain ineligible for biased locking 

  assert (!mark->has_bias_pattern(), "invariant") ; 

 

  if (mark->is_neutral()) {

    hash = mark->hash();              // this is a normal header

    if (hash) {                       // if it has hash, just return it

      return hash;

    }

    hash = get_next_hash(Self, obj);  // allocate a new hash code

    temp = mark->copy_set_hash(hash); // merge the hash code into header

    // use (machine word version) atomic operation to install the hash

    test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);

    if (test == mark) {

      return hash;

    }

    // If atomic operation failed, we must inflate the header

    // into heavy weight monitor. We could add more code here

    // for fast path, but it does not worth the complexity.

  } else if (mark->has_monitor()) {

    monitor = mark->monitor();

    temp = monitor->header();

    assert (temp->is_neutral(), "invariant") ; 

    hash = temp->hash();

    if (hash) {

      return hash;

    }

    // Skip to the following code to reduce code size

  } else if (Self->is_lock_owned((address)mark->locker())) {

    temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned

    assert (temp->is_neutral(), "invariant") ; 

    hash = temp->hash();              // by current thread, check if the displaced

    if (hash) {                       // header contains hash code

      return hash;

    }

    // WARNING:

    //   The displaced header is strictly immutable.

    // It can NOT be changed in ANY cases. So we have 

    // to inflate the header into heavyweight monitor

    // even the current thread owns the lock. The reason

    // is the BasicLock (stack slot) will be asynchronously 

    // read by other threads during the inflate() function.

    // Any change to stack may not propagate to other threads

    // correctly.

  }

 

  // Inflate the monitor to set hash code

  monitor = ObjectSynchronizer::inflate(Self, obj);

  // Load displaced header and check it has hash code

  mark = monitor->header();

  assert (mark->is_neutral(), "invariant") ; 

  hash = mark->hash();

  if (hash == 0) {

    hash = get_next_hash(Self, obj);

    temp = mark->copy_set_hash(hash); // merge hash code into header

    assert (temp->is_neutral(), "invariant") ; 

    test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);

    if (test != mark) {

      // The only update to the header in the monitor (outside GC)

      // is install the hash code. If someone add new usage of

      // displaced header, please update this code

      hash = test->hash();

      assert (test->is_neutral(), "invariant") ; 

      assert (hash != 0, "Trivial unexpected object/monitor header usage.");

    }

  }

  // We finally get the hash

  return hash;

}


你可能感兴趣的:(HashCode)