static VM_Lock allocate () {
static VM_Lock allocate () throws VM_PragmaLogicallyUninterruptible  {
  static void init() throws VM_PragmaInterruptible {    lockAllocationMutex = new VM_ProcessorLock();    VM_Scheduler.locks  = new VM_Lock[MAX_LOCKS+1]; // don't use slot 0    if (VM.VerifyAssertions) // check that each potential lock is addressable      VM.assert((VM_Scheduler.locks.length-1<=(VM_ThinLockConstants.TL_LOCK_ID_MASK>>>VM_ThinLockConstants.TL_LOCK_ID_SHIFT))                || (VM_ThinLockConstants.TL_LOCK_ID_MASK==-1));  }    /**   * Delivers up an unassigned heavy-weight lock.  Locks are allocated   * from processor specific regions or lists, so normally no synchronization   * is required to obtain a lock.   *   * Collector threads cannot use heavy-weight locks.   *   * @return a free VM_Lock; or <code>null</code>, if garbage collection is not enabled   */  static VM_Lock allocate () {    VM_Processor mine = VM_Processor.getCurrentProcessor();    if (mine.isInitialized && !mine.threadSwitchingEnabled()) return null; // Collector threads can't use heavy locks because they don't fix up their stacks after moving objects    if ((mine.freeLocks == 0) && (0 < globalFreeLocks) && balanceFreeLocks) {      localizeFreeLocks();    }    VM_Lock l = mine.freeLock;    if (l != null) {      mine.freeLock = l.nextFreeLock;      l.nextFreeLock = null;      mine.freeLocks--;      l.active = true;    } else {      l = new VM_Lock(); // may cause thread switch (and processor loss)      mine = VM_Processor.getCurrentProcessor();      if (mine.lastLockIndex < mine.nextLockIndex) {	lockAllocationMutex.lock();	mine.nextLockIndex = 1 + (LOCK_ALLOCATION_UNIT_SIZE * lockUnitsAllocated++);	lockAllocationMutex.unlock();	mine.lastLockIndex = mine.nextLockIndex + LOCK_ALLOCATION_UNIT_SIZE - 1;	if (MAX_LOCKS <= mine.lastLockIndex) {	  VM.sysWriteln("Too many fat locks on processor ", mine.id); // make MAX_LOCKS bigger? we can keep going??	  VM.sysFail("Exiting VM with fatal error");	  return null;	}      }      l.index = mine.nextLockIndex++;      VM_Scheduler.locks[l.index] = l;      l.active = true;      VM_Magic.sync(); // make sure other processors see lock initialization.  Note: Derek and I BELIEVE that an isync is not required in the other processor because the lock is newly allocated - Bowen    }    mine.locksAllocated++;    return l;  }