/// <summary>
        /// Assigns a hash code to the object in a thread-safe way.
        /// </summary>
        private static unsafe int AssignHashCode(int *pHeader)
        {
            int newHash = RuntimeHelpers.GetNewHashCode() & MASK_HASHCODE_INDEX;
            int bitAndValue;

            // Never use the zero hash code.  SyncTable treats the zero value as "not assigned".
            if (newHash == 0)
            {
                newHash = 1;
            }

            while (true)
            {
                int oldBits = Volatile.Read(ref *pHeader);
                bitAndValue = oldBits & (BIT_SBLK_IS_HASHCODE | MASK_HASHCODE_INDEX);
                if (bitAndValue != 0)
                {
                    // The header already stores some value
                    break;
                }

                // The header stores nothing.  Try to store the hash code.
                int newBits = oldBits | BIT_SBLK_IS_HASHCODE | newHash;
                if (Interlocked.CompareExchange(ref *pHeader, newBits, oldBits) == oldBits)
                {
                    return(newHash);
                }

                // Another thread modified the header; try again
            }

            if ((bitAndValue & BIT_SBLK_IS_HASHCODE) == 0)
            {
                // Set the hash code in SyncTable.  This call will resolve the potential race.
                return(SyncTable.SetHashCode(bitAndValue, newHash));
            }

            // Another thread set the hash code, use it
            Debug.Assert((bitAndValue & ~BIT_SBLK_IS_HASHCODE) != 0);
            return(bitAndValue & ~BIT_SBLK_IS_HASHCODE);
        }