@Uninterruptible
 @NoNullCheck
 public static boolean holdsLock(Object o, Offset lockOffset, RVMThread thread) {
   for (int cnt = 0; ; ++cnt) {
     int tid = thread.getLockingId();
     Word bits = Magic.getWordAtOffset(o, lockOffset);
     if (bits.and(TL_STAT_MASK).EQ(TL_STAT_BIASABLE)) {
       // if locked, then it is locked with a thin lock
       return bits.and(TL_THREAD_ID_MASK).toInt() == tid && !bits.and(TL_LOCK_COUNT_MASK).isZero();
     } else if (bits.and(TL_STAT_MASK).EQ(TL_STAT_THIN)) {
       return bits.and(TL_THREAD_ID_MASK).toInt() == tid;
     } else {
       if (VM.VerifyAssertions) VM._assert(bits.and(TL_STAT_MASK).EQ(TL_STAT_FAT));
       // if locked, then it is locked with a fat lock
       Lock l = Lock.getLock(getLockIndex(bits));
       if (l != null) {
         l.mutex.lock();
         boolean result = (l.getOwnerId() == tid && l.getLockedObject() == o);
         l.mutex.unlock();
         return result;
       }
     }
     RVMThread.yieldNoHandshake();
   }
 }
  @NoInline
  @NoNullCheck
  @Unpreemptible
  public static void lock(Object o, Offset lockOffset) {
    if (STATS) fastLocks++;

    Word threadId = Word.fromIntZeroExtend(RVMThread.getCurrentThread().getLockingId());

    for (int cnt = 0; ; cnt++) {
      Word old = Magic.getWordAtOffset(o, lockOffset);
      Word stat = old.and(TL_STAT_MASK);
      boolean tryToInflate = false;
      if (stat.EQ(TL_STAT_BIASABLE)) {
        Word id = old.and(TL_THREAD_ID_MASK);
        if (id.isZero()) {
          if (ENABLE_BIASED_LOCKING) {
            // lock is unbiased, bias it in our favor and grab it
            if (Synchronization.tryCompareAndSwap(
                o, lockOffset, old, old.or(threadId).plus(TL_LOCK_COUNT_UNIT))) {
              Magic.isync();
              return;
            }
          } else {
            // lock is unbiased but biasing is NOT allowed, so turn it into
            // a thin lock
            if (Synchronization.tryCompareAndSwap(
                o, lockOffset, old, old.or(threadId).or(TL_STAT_THIN))) {
              Magic.isync();
              return;
            }
          }
        } else if (id.EQ(threadId)) {
          // lock is biased in our favor
          Word changed = old.plus(TL_LOCK_COUNT_UNIT);
          if (!changed.and(TL_LOCK_COUNT_MASK).isZero()) {
            setDedicatedU16(o, lockOffset, changed);
            return;
          } else {
            tryToInflate = true;
          }
        } else {
          if (casFromBiased(o, lockOffset, old, biasBitsToThinBits(old), cnt)) {
            continue; // don't spin, since it's thin now
          }
        }
      } else if (stat.EQ(TL_STAT_THIN)) {
        Word id = old.and(TL_THREAD_ID_MASK);
        if (id.isZero()) {
          if (Synchronization.tryCompareAndSwap(o, lockOffset, old, old.or(threadId))) {
            Magic.isync();
            return;
          }
        } else if (id.EQ(threadId)) {
          Word changed = old.plus(TL_LOCK_COUNT_UNIT);
          if (changed.and(TL_LOCK_COUNT_MASK).isZero()) {
            tryToInflate = true;
          } else if (Synchronization.tryCompareAndSwap(o, lockOffset, old, changed)) {
            Magic.isync();
            return;
          }
        } else if (cnt > retryLimit) {
          tryToInflate = true;
        }
      } else {
        if (VM.VerifyAssertions) VM._assert(stat.EQ(TL_STAT_FAT));
        // lock is fat.  contend on it.
        if (Lock.getLock(getLockIndex(old)).lockHeavy(o)) {
          return;
        }
      }

      if (tryToInflate) {
        if (STATS) slowLocks++;
        // the lock is not fat, is owned by someone else, or else the count wrapped.
        // attempt to inflate it (this may fail, in which case we'll just harmlessly
        // loop around) and lock it (may also fail, if we get the wrong lock).  if it
        // succeeds, we're done.
        // NB: this calls into our attemptToMarkInflated() method, which will do the
        // Right Thing if the lock is biased to someone else.
        if (inflateAndLock(o, lockOffset)) {
          return;
        }
      } else {
        RVMThread.yieldNoHandshake();
      }
    }
  }