static void unlock(Object o, int lockOffset) throws NoInlinePragma {
static void unlock(Object o, Offset lockOffset) throws NoInlinePragma {
  static void unlock(Object o, int lockOffset) throws NoInlinePragma {    VM_Magic.sync(); // prevents stale data from being seen by next owner of the lock    while (true) { // spurious contention detected      Word old = VM_Magic.prepareWord(o, lockOffset);      Word id  = old.and(TL_THREAD_ID_MASK.or(TL_FAT_LOCK_MASK));      Word threadId = Word.fromIntZeroExtend(VM_Processor.getCurrentProcessor().threadId);      if (id.NE(threadId)) { // not normal case        if (!(old.and(TL_FAT_LOCK_MASK).isZero())) { // o has a heavy lock          int index = old.and(TL_LOCK_ID_MASK).rshl(TL_LOCK_ID_SHIFT).toInt();          VM_Scheduler.locks[index].unlockHeavy(o);           // note that unlockHeavy has issued a sync          return;        }         VM_Scheduler.trace("VM_Lock", "unlock error: thin lock word = ", old.toAddress());        VM_Scheduler.trace("VM_Lock", "unlock error: thin lock word = ", VM_Magic.objectAsAddress(o));        // VM_Scheduler.trace("VM_Lock", VM_Thread.getCurrentThread().toString(), 0);        VM_Lock.raiseIllegalMonitorStateException("thin unlocking", o);      }      if (old.and(TL_LOCK_COUNT_MASK).isZero()) { // get count, 0 is the last lock        Word changed = old.and(TL_UNLOCK_MASK);        if (VM_Magic.attemptWord(o, lockOffset, old, changed)) {          return; // unlock succeeds        }         continue;      }      // more than one lock      // decrement recursion count      Word changed = old.toAddress().sub(TL_LOCK_COUNT_UNIT).toWord();       if (VM_Magic.attemptWord(o, lockOffset, old, changed)) {        return; // unlock succeeds      }    }  }