/*
 *  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.utility.alloc;

import org.mmtk.policy.Space;
import org.mmtk.utility.Constants;
import org.mmtk.utility.Conversions;
import org.mmtk.utility.Log;
import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver;
import org.mmtk.vm.VM;
import org.vmmagic.pragma.Inline;
import org.vmmagic.pragma.NoInline;
import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.Extent;
import org.vmmagic.unboxed.ObjectReference;
import org.vmmagic.unboxed.Offset;
import org.vmmagic.unboxed.Word;

/**
 * This class implements a bump pointer allocator that allows linearly
 * scanning through the allocated objects. In order to achieve this in the
 * face of parallelism it maintains a header at a region (1 or more blocks)
 * granularity.
 *
 * Intra-block allocation is fast, requiring only a load, addition comparison
 * and store.  If a block boundary is encountered the allocator will
 * request more memory (virtual and actual).
 *
 * In the current implementation the scanned objects maintain affinity
 * with the thread that allocated the objects in the region. In the future
 * it is anticipated that subclasses should be allowed to choose to improve
 * load balancing during the parallel scan.
 *
 * Each region is laid out as follows:
 *
 *  +-------------+-------------+-------------+---------------
 *  | Region  End | Next Region |  Data  End  | Data -->
 * +-------------+-------------+-------------+---------------
 *
 * The minimum region size is 32768 bytes, so the 3 or 4 word overhead is
 * less than 0.05% of all space.
 *
 * An intended enhancement is to facilitate a reallocation operation
 * where a second cursor is maintained over earlier regions (and at the
 * limit a lower location in the same region). This would be accompianied
 * with an alternative slow path that would allow reuse of empty regions.
 *
 * This class relies on the supporting virtual machine implementing the
 * getNextObject and related operations.
 */
@Uninterruptible public class BumpPointer extends Allocator
  implements Constants {

  /****************************************************************************
   *
   * Class variables
   */

  // Block size defines slow path periodicity.
  private static final int LOG_DEFAULT_STEP_SIZE = 30; // 1G: let the external slow path dominate
  private static final int STEP_SIZE = 1<<(SUPPORT_CARD_SCANNING ? LOG_CARD_BYTES : LOG_DEFAULT_STEP_SIZE);
  protected static final int LOG_BLOCK_SIZE = LOG_BYTES_IN_PAGE + 3;
  protected static final Word BLOCK_MASK = Word.one().lsh(LOG_BLOCK_SIZE).minus(Word.one());
  private static final int BLOCK_SIZE = (1<<LOG_BLOCK_SIZE);


  // Offsets into header
  protected static final Offset REGION_LIMIT_OFFSET = Offset.zero();
  protected static final Offset NEXT_REGION_OFFSET = REGION_LIMIT_OFFSET.plus(BYTES_IN_ADDRESS);
  protected static final Offset DATA_END_OFFSET = NEXT_REGION_OFFSET.plus(BYTES_IN_ADDRESS);

  // Data must start particle-aligned.
  protected static final Offset DATA_START_OFFSET = alignAllocationNoFill(
      Address.zero().plus(DATA_END_OFFSET.plus(BYTES_IN_ADDRESS)),
      MIN_ALIGNMENT, 0).toWord().toOffset();
  protected static final Offset MAX_DATA_START_OFFSET = alignAllocationNoFill(
      Address.zero().plus(DATA_END_OFFSET.plus(BYTES_IN_ADDRESS)),
      MAX_ALIGNMENT, 0).toWord().toOffset();

  public static final int MINIMUM_DATA_SIZE = (1 << LOG_BLOCK_SIZE) - MAX_DATA_START_OFFSET.toInt();

  private static final boolean VERBOSE = false;

  /****************************************************************************
   *
   * Instance variables
   */
  protected Address cursor; // insertion point
  private Address internalLimit; // current internal slow-path sentinal for bump pointer
  private Address limit; // current external slow-path sentinal for bump pointer
  protected Space space; // space this bump pointer is associated with
  protected Address initialRegion; // first contiguous region
  protected final boolean allowScanning; // linear scanning is permitted if true
  protected Address region; // current contiguous region


  /**
   * Constructor.
   *
   * @param space The space to bump point into.
   * @param allowScanning Allow linear scanning of this region of memory.
   */
  protected BumpPointer(Space space, boolean allowScanning) {
    this.space = space;
    this.allowScanning = allowScanning;
    reset();
  }

  /**
   * Reset the allocator. Note that this does not reset the space.
   * This is must be done by the caller.
   */
  public final void reset() {
    cursor = Address.zero();
    limit = Address.zero();
    internalLimit = Address.zero();
    initialRegion = Address.zero();
    region = Address.zero();
  }

  /**
   * Re-associate this bump pointer with a different space. Also
   * reset the bump pointer so that it will use the new space
   * on the next call to <code>alloc</code>.
   *
   * @param space The space to associate the bump pointer with.
   */
  public final void rebind(Space space) {
    reset();
    this.space = space;
  }

  /**
   * Allocate space for a new object.  This is frequently executed code and
   * the coding is deliberaetly sensitive to the optimizing compiler.
   * After changing this, always check the IR/MC that is generated.
   *
   * @param bytes The number of bytes allocated
   * @param align The requested alignment
   * @param offset The offset from the alignment
   * @return The address of the first byte of the allocated region
   */
  @Inline
  public final Address alloc(int bytes, int align, int offset) {
    Address start = alignAllocationNoFill(cursor, align, offset);
    Address end = start.plus(bytes);
    if (end.GT(internalLimit))
      return allocSlow(start, end, align, offset);
    fillAlignmentGap(cursor, start);
    cursor = end;
    return start;
  }

 /**
  * Internal allocation slow path.  This is called whenever the bump
  * pointer reaches the internal limit.  The code is forced out of
  * line.  If required we perform an external slow path take, which
  * we inline into this method since this is already out of line.
  *
  * @param start The start address for the pending allocation
 * @param end The end address for the pending allocation
 * @param align The requested alignment
 * @param offset The offset from the alignment
  * @return The address of the first byte of the allocated region
  */
  @NoInline
  private Address allocSlow(Address start, Address end, int align,
      int offset) {
    Address rtn = null;
    Address card = null;
    if (SUPPORT_CARD_SCANNING)
      card = getCard(start.plus(CARD_MASK)); // round up
    if (end.GT(limit)) { /* external slow path */
      rtn = allocSlowInline(end.diff(start).toInt(), align, offset);
      if (SUPPORT_CARD_SCANNING && card.NE(getCard(rtn.plus(CARD_MASK))))
        card = getCard(rtn); // round down
    } else {             /* internal slow path */
      while (internalLimit.LE(end))
        internalLimit = internalLimit.plus(STEP_SIZE);
      if (internalLimit.GT(limit))
        internalLimit = limit;
      fillAlignmentGap(cursor, start);
      cursor = end;
      rtn = start;
    }
    if (SUPPORT_CARD_SCANNING && !rtn.isZero())
      createCardAnchor(card, rtn, end.diff(start).toInt());
    return rtn;
  }

  /**
   * Given an allocation which starts a new card, create a record of
   * where the start of the object is relative to the start of the
   * card.
   *
   * @param card An address that lies within the card to be marked
   * @param start The address of an object which creates a new card.
   * @param bytes The size of the pending allocation in bytes (used for debugging)
   */
  private void createCardAnchor(Address card, Address start, int bytes) {
    if (VM.VERIFY_ASSERTIONS) {
      VM.assertions._assert(allowScanning);
      VM.assertions._assert(card.EQ(getCard(card)));
      VM.assertions._assert(start.diff(card).sLE(MAX_DATA_START_OFFSET));
      VM.assertions._assert(start.diff(card).toInt() >= -CARD_MASK);
    }
    while (bytes > 0) {
      int offset = start.diff(card).toInt();
      getCardMetaData(card).store(offset);
      card = card.plus(1 << LOG_CARD_BYTES);
      bytes -= (1 << LOG_CARD_BYTES);
    }
  }

  /**
   * Return the start of the card corresponding to a given address.
   *
   * @param address The address for which the card start is required
   * @return The start of the card containing the address
   */
  private static Address getCard(Address address) {
    return address.toWord().and(Word.fromIntSignExtend(CARD_MASK).not()).toAddress();
  }

  /**
   * Return the address of the metadata for a card, given the address of the card.
   * @param card The address of some card
   * @return The address of the metadata associated with that card
   */
  private static Address getCardMetaData(Address card) {
    Address metadata = EmbeddedMetaData.getMetaDataBase(card);
    return metadata.plus(EmbeddedMetaData.getMetaDataOffset(card, LOG_CARD_BYTES-LOG_CARD_META_SIZE, LOG_CARD_META_SIZE));
  }

  /**
   * External allocation slow path (called by superclass when slow path is
   * actually taken.  This is necessary (rather than a direct call
   * from the fast path) because of the possibility of a thread switch
   * and corresponding re-association of bump pointers to kernel
   * threads.
   *
   * @param bytes The number of bytes allocated
   * @param offset The offset from the alignment
   * @param align The requested alignment
   * @return The address of the first byte of the allocated region or
   * zero on failure
   */
  @Override
  protected final Address allocSlowOnce(int bytes, int align, int offset) {
    /* Check we have been bound to a space */
    if (space == null) {
      VM.assertions.fail("Allocation on unbound bump pointer.");
    }

    /* Check if we already have a block to use */
    if (allowScanning && !region.isZero()) {
      Address nextRegion = getNextRegion(region);
      if (!nextRegion.isZero()) {
        return consumeNextRegion(nextRegion, bytes, align, offset);
      }
    }

    /* Acquire space, block aligned, that can accommodate the request */
    Extent blockSize = Word.fromIntZeroExtend(bytes).plus(BLOCK_MASK)
                       .and(BLOCK_MASK.not()).toExtent();
    Address start = space.acquire(Conversions.bytesToPages(blockSize));

    if (start.isZero()) return start; // failed allocation

    if (!allowScanning) { // simple allocator
      if (start.NE(limit)) cursor = start;  // discontiguous
      updateLimit(start.plus(blockSize), start, bytes);
    } else                // scannable allocator
      updateMetaData(start, blockSize, bytes);
    return alloc(bytes, align, offset);
  }

  /**
   * Update the limit pointer.  As a side effect update the internal limit
   * pointer appropriately.
   *
   * @param newLimit The new value for the limit pointer
   * @param start The start of the region to be allocated into
   * @param bytes The size of the pending allocation (if any).
   */
  @Inline
  protected final void updateLimit(Address newLimit, Address start, int bytes) {
    limit = newLimit;
    internalLimit = start.plus(STEP_SIZE);
    if (internalLimit.GT(limit))
      internalLimit = limit;
    else {
      while (internalLimit.LT(cursor.plus(bytes)))
        internalLimit = internalLimit.plus(STEP_SIZE);
      if (VM.VERIFY_ASSERTIONS)
        VM.assertions._assert(internalLimit.LE(limit));
    }
  }

  /**
   * A bump pointer chunk/region has been consumed but the contiguous region
   * is available, so consume it and then return the address of the start
   * of a memory region satisfying the outstanding allocation request.  This
   * is relevant when re-using memory, as in a mark-compact collector.
   *
   * @param nextRegion The region to be consumed
   * @param bytes The number of bytes allocated
   * @param align The requested alignment
   * @param offset The offset from the alignment
   * @return The address of the first byte of the allocated region or
   * zero on failure
   */
  private Address consumeNextRegion(Address nextRegion, int bytes, int align,
        int offset) {
    setNextRegion(region,cursor);
    region = nextRegion;
    cursor = getDataStart(nextRegion);
    updateLimit(getRegionLimit(nextRegion), nextRegion, bytes);
    setDataEnd(nextRegion,Address.zero());
    VM.memory.zero(cursor, limit.diff(cursor).toWord().toExtent());
    reusePages(Conversions.bytesToPages(limit.diff(region)));

    return alloc(bytes, align, offset);
  }

  /******************************************************************************
   *
   *   Accessor methods for the region metadata fields.
   *
   */

  /**
   * The first offset in a region after the header
   * @param region The region
   * @return The lowest address at which data can be stored
   */
  @Inline
  public static Address getDataStart(Address region) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    return region.plus(DATA_START_OFFSET);
  }

  /**
   * The next region in the linked-list of regions
   * @param region The region
   * @return The next region in the list
   */
  @Inline
  public static Address getNextRegion(Address region) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    Address result = region.plus(NEXT_REGION_OFFSET).loadAddress();
    return result;
  }

  /**
   * Set the next region in the linked-list of regions
   * @param region The region
   * @param the next region in the list
   */
  @Inline
  public static void setNextRegion(Address region, Address nextRegion) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!nextRegion.EQ(Address.fromIntZeroExtend(0xdeadbeef)));
    region.store(nextRegion,NEXT_REGION_OFFSET);
  }

  /**
   * Clear the next region pointer in the linked-list of regions
   * @param region The region
   */
  @Inline
  public static void clearNextRegion(Address region) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    region.store(Address.zero(),NEXT_REGION_OFFSET);
  }

  /**
   * @param region The bump-pointer region
   * @return The DATA_END address from the region header
   */
  @Inline
  public static Address getDataEnd(Address region) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    return region.plus(DATA_END_OFFSET).loadAddress();
  }

  /**
   * @param region The bump-pointer region
   * @param endAddress The new DATA_END address from the region header
   */
  public static void setDataEnd(Address region, Address endAddress) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    region.store(endAddress, DATA_END_OFFSET);
    if (VERBOSE) {
      Log.write("setDataEnd(");
      Log.write(region);
      Log.write(",");
      Log.write(endAddress);
      Log.writeln(")");
    }
  }

  /**
   * Return the end address of the given region.
   * @param region The region.
   * @return the allocation limit of the region.
   */
  public static Address getRegionLimit(Address region) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    return region.plus(REGION_LIMIT_OFFSET).loadAddress();
  }

  /**
   * Return the end address of the given region.
   * @param region The region.
   * @return the allocation limit of the region.
   */
  public static void setRegionLimit(Address region, Address limit) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    region.plus(REGION_LIMIT_OFFSET).store(limit);
  }

  /**
   * @param region The region.
   * @return {@code true} if the address is region-aligned
   */
  public static boolean isRegionAligned(Address region) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero());
    return region.toWord().and(BLOCK_MASK).isZero();
  }

  /**
   * Sanity check a region header
   * @param region Region to check
   */
  public static void checkRegionMetadata(Address region) {
    if (VM.VERIFY_ASSERTIONS) {
      Address nextRegion = getNextRegion(region);
      Address dataStart = getDataStart(region);
      Address dataEnd = getDataEnd(region);
      Address regionLimit = getRegionLimit(region);

      VM.assertions._assert(nextRegion.isZero() || isRegionAligned(nextRegion));
      VM.assertions._assert(dataEnd.GE(dataStart));
      if (dataEnd.GT(regionLimit)) {
        Log.write("dataEnd="); Log.write(dataEnd);
        Log.write(", regionLimit="); Log.writeln(regionLimit);
      }
      VM.assertions._assert(dataEnd.LE(regionLimit));
      VM.assertions._assert(regionLimit.EQ(region.plus(BLOCK_SIZE)));
    }

  }
  /**
   * Update the metadata to reflect the addition of a new region.
   *
   * @param start The start of the new region
   * @param size The size of the new region (rounded up to block-alignment)
   */
  @Inline
  private void updateMetaData(Address start, Extent size, int bytes) {
    if (initialRegion.isZero()) {
      /* this is the first allocation */
      initialRegion = start;
      region = start;
      cursor = region.plus(DATA_START_OFFSET);
    } else if (limit.NE(start) ||
               region.diff(start.plus(size)).toWord().toExtent().GT(maximumRegionSize())) {
      /* non contiguous or over-size, initialize new region */
      setNextRegion(region,start);
      setDataEnd(region,cursor);
      region = start;
      cursor = start.plus(DATA_START_OFFSET);
    }
    updateLimit(start.plus(size), start, bytes);
    setRegionLimit(region,limit);
  }

  /**
   * Gather data for GCspy. <p>
   * This method calls the drivers linear scanner to scan through
   * the objects allocated by this bump pointer.
   *
   * @param driver The GCspy driver for this space.
   */
  public void gcspyGatherData(LinearSpaceDriver driver) {
    //driver.setRange(space.getStart(), cursor);
    driver.setRange(space.getStart(), limit);
    this.linearScan(driver.getScanner());
  }

  /**
   * Gather data for GCspy. <p>
   * This method calls the drivers linear scanner to scan through
   * the objects allocated by this bump pointer.
   *
   * @param driver The GCspy driver for this space.
   * @param scanSpace The space to scan
   */
  public void gcspyGatherData(LinearSpaceDriver driver, Space scanSpace) {
    //TODO can scanSpace ever be different to this.space?
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(scanSpace == space, "scanSpace != space");

    //driver.setRange(scanSpace.getStart(), cursor);
    Address start = scanSpace.getStart();
    driver.setRange(start, limit);

    if (false) {
      Log.write("\nBumpPointer.gcspyGatherData set Range "); Log.write(scanSpace.getStart());
      Log.write(" to "); Log.writeln(limit);
      Log.write("BumpPointergcspyGatherData scan from "); Log.writeln(initialRegion);
    }

    linearScan(driver.getScanner());
  }


  /**
   * Perform a linear scan through the objects allocated by this bump pointer.
   *
   * @param scanner The scan object to delegate scanning to.
   */
  @Inline
  public final void linearScan(LinearScan scanner) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allowScanning);
    /* Has this allocator ever allocated anything? */
    if (initialRegion.isZero()) return;

    /* Loop through active regions or until the last region */
    Address start = initialRegion;
    while (!start.isZero()) {
      scanRegion(scanner, start); // Scan this region
      start = getNextRegion(start); // Move on to next
    }
  }

  /**
   * Perform a linear scan through a single contiguous region
   *
   * @param scanner The scan object to delegate to.
   * @param start The start of this region
   */
  @Inline
  private void scanRegion(LinearScan scanner, Address start) {
    /* Get the end of this region */
    Address dataEnd = start.plus(DATA_END_OFFSET).loadAddress();

    /* dataEnd = zero represents the current region. */
    Address currentLimit = (dataEnd.isZero() ? cursor : dataEnd);
    if (currentLimit.EQ(start.plus(DATA_END_OFFSET).plus(BYTES_IN_ADDRESS))) {
      /* Empty region, so we can not call getObjectFromStartAddress() */
      return;
    }

    ObjectReference current = VM.objectModel.getObjectFromStartAddress(start.plus(DATA_START_OFFSET));

    /* Loop through each object up to the limit */
    do {
      /* Read end address first, as scan may be destructive */
      Address currentObjectEnd = VM.objectModel.getObjectEndAddress(current);
      scanner.scan(current);
      if (currentObjectEnd.GE(currentLimit)) {
        /* We have scanned the last object */
        break;
      }
      /* Find the next object from the start address (dealing with alignment gaps, etc.) */
      ObjectReference next = VM.objectModel.getObjectFromStartAddress(currentObjectEnd);
      if (VM.VERIFY_ASSERTIONS) {
        /* Must be monotonically increasing */
        VM.assertions._assert(next.toAddress().GT(current.toAddress()));
      }
      current = next;
    } while (true);
  }

  /**
   * Some pages are about to be re-used to satisfy a slow path request.
   * @param pages The number of pages.
   */
  protected void reusePages(int pages) {
    VM.assertions.fail("Subclasses that reuse regions must override this method.");
  }

  /**
   * Maximum size of a single region. Important for children that implement
   * load balancing or increments based on region size.
   * @return the maximum region size
   */
  protected Extent maximumRegionSize() { return Extent.max(); }

  /** @return the current cursor value */
  public final Address getCursor() { return cursor; }
  /** @return the space associated with this bump pointer */
  @Override
  public final Space getSpace() { return space; }

  /**
   * Print out the status of the allocator (for debugging)
   */
  public final void show() {
    Log.write("cursor = "); Log.write(cursor);
    if (allowScanning) {
      Log.write(" region = "); Log.write(region);
    }
    Log.write(" limit = "); Log.writeln(limit);
  }
}
