/*
 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
 *
 *  This file is licensed to You under the Eclipse Public License (EPL);
 *  You may not use this file except in compliance with the License. You
 *  may obtain a copy of the License at
 *
 *      http://www.opensource.org/licenses/eclipse-1.0.php
 *
 *  See the COPYRIGHT.txt file distributed with this work for information
 *  regarding copyright ownership.
 */
package org.mmtk.policy.immix;

import org.mmtk.plan.Plan;
import org.mmtk.policy.Space;
import org.mmtk.utility.Constants;
import org.mmtk.vm.VM;
import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.AddressArray;

@Uninterruptible
public final class ChunkList implements Constants {
  private static final int LOG_PAGES_IN_CHUNK_MAP_BLOCK = 0;
  private static final int ENTRIES_IN_CHUNK_MAP_BLOCK = (BYTES_IN_PAGE<<LOG_PAGES_IN_CHUNK_MAP_BLOCK)>>LOG_BYTES_IN_ADDRESS;
  private static final int CHUNK_MAP_BLOCKS = 1<<4;
  private static final int MAX_ENTRIES_IN_CHUNK_MAP = ENTRIES_IN_CHUNK_MAP_BLOCK * CHUNK_MAP_BLOCKS;
  private AddressArray chunkMap =  AddressArray.create(CHUNK_MAP_BLOCKS);
  private int chunkMapLimit = -1;
  private int chunkMapCursor = -1;

  void reset() {
    chunkMapLimit = chunkMapCursor;
  }

  public Address getHeadChunk() {
    if (chunkMapLimit < 0)
      return Address.zero();
    else
      return getMapAddress(0).loadAddress();
  }

  public Address getTailChunk() {
    if (chunkMapLimit < 0)
      return Address.zero();
    else
      return getMapAddress(chunkMapLimit).loadAddress();
  }

  void addNewChunkToMap(Address chunk) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
    if (chunkMapCursor == MAX_ENTRIES_IN_CHUNK_MAP - 1)
      consolidateMap();
    chunkMapCursor++;
    int index = getChunkIndex(chunkMapCursor);
    int map = getChunkMap(chunkMapCursor);
    if (map >= CHUNK_MAP_BLOCKS) {
      Space.printUsageMB();
      VM.assertions.fail("Overflow of chunk map!");
    }
    if (chunkMap.get(map).isZero()) {
      Address tmp = Plan.metaDataSpace.acquire(1<<LOG_PAGES_IN_CHUNK_MAP_BLOCK);
      if (tmp.isZero()) {
        Space.printUsageMB();
        VM.assertions.fail("Failed to allocate space for chunk map.  Is metadata virtual memory exhausted?");
      }
      chunkMap.set(map, tmp);
    }
    Address entry = chunkMap.get(map).plus(index<<LOG_BYTES_IN_ADDRESS);
    entry.store(chunk);
    Chunk.setMap(chunk, chunkMapCursor);
    if (VM.VERIFY_ASSERTIONS) checkMap();
  }

  void removeChunkFromMap(Address chunk) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
    int entry = Chunk.getMap(chunk);
    getMapAddress(entry).store(Address.zero());  // zero it it
    Chunk.setMap(chunk, -entry);
    if (VM.VERIFY_ASSERTIONS) checkMap();
  }

  private int getChunkIndex(int entry) { return entry & (ENTRIES_IN_CHUNK_MAP_BLOCK - 1);}
  private int getChunkMap(int entry) {return entry & ~(ENTRIES_IN_CHUNK_MAP_BLOCK - 1);}

  private Address getMapAddress(int entry) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(entry >= 0);
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(entry <= chunkMapCursor);
    int index = getChunkIndex(entry);
    int map = getChunkMap(entry);
    return chunkMap.get(map).plus(index<<LOG_BYTES_IN_ADDRESS);
  }

  /**
   * A chunk iterator.  Return the next chunk in sequence, or null if the
   * next chunk is the same chunk (ie there is only one chunk in the iterator).
   *
   * @param chunk The chunk
   * @return The next chunk in the sequence, or null if next is chunk.
   */
  public Address nextChunk(Address chunk) {
    return nextChunk(chunk, chunk);
  }

  /**
   * A chunk iterator.  Return the next chunk in sequence, or null if the
   * next chunk is limit.
   *
   * @param chunk The chunk
   * @param limit The starting point (if next is equal to this, we're done)
   * @return The next chunk in the sequence, or null if next is limit.
   */
  private Address nextChunk(final Address chunk, final Address limit) {
    return nextChunk(chunk, Chunk.getMap(limit), 1);
  }

  /**
   * A chunk iterator.  Return the next chunk in sequence, strided
   * by stride steps, or null if the next chunk is start.
   *
   * @param chunk The chunk
   * @param start The point where this iterator started, which defines its end-point
   * @param stride The stride by which the iterator should be stepped
   * @return The next chunk in the sequence, or null if next is start.
   */
  public Address nextChunk(final Address chunk, final int start, final int stride) {
    if (VM.VERIFY_ASSERTIONS) checkMap();
    return nextChunk(Chunk.getMap(chunk), start, stride);
  }

  /**
   * A chunk iterator.  Return the next chunk in sequence, strided
   * by stride steps, or null if the next chunk is start.
   *
   * @param entry The entry we're currently up to
   * @param start The point where this iterator started, which defines its end-point
   * @param stride The stride by which the iterator should be stepped
   * @return The next chunk in the sequence, or null if next is start.
   */
  private Address nextChunk(int entry, final int start, final int stride) {
    if (VM.VERIFY_ASSERTIONS) checkMap();
    Address chunk;
    do {
      entry += stride;
      if (entry > chunkMapLimit) { entry = entry % stride; }
      chunk = getMapAddress(entry).loadAddress();
    } while (chunk.isZero() && entry != start);
    return entry == start ? Address.zero() : chunk;
  }

  public Address firstChunk(int ordinal, int stride) {
    if (ordinal > chunkMapCursor) return Address.zero();
    if (VM.VERIFY_ASSERTIONS) checkMap();
    Address chunk = getMapAddress(ordinal).loadAddress();
    return chunk.isZero() ? nextChunk(ordinal, ordinal, stride) : chunk;
  }

  private void checkMap() {
    VM.assertions._assert(chunkMapLimit <= chunkMapCursor);
    for (int entry = 0; entry <= chunkMapCursor; entry++) {
      Address chunk = getMapAddress(entry).loadAddress();
      if (!chunk.isZero())
        VM.assertions._assert(Chunk.getMap(chunk) == entry);
    }
  }

  public void consolidateMap() {
    int oldCursor = 0;
    int newCursor = -1;
    while (oldCursor <= chunkMapCursor) {
      Address chunk = getMapAddress(oldCursor).loadAddress();
      if (!chunk.isZero()) {
        getMapAddress(++newCursor).store(chunk);
        Chunk.setMap(chunk, newCursor);
      }
      oldCursor++;
    }
    chunkMapCursor = newCursor;
    chunkMapLimit = newCursor;
    if (VM.VERIFY_ASSERTIONS) checkMap();
  }
}
