/*
 *  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 static org.mmtk.policy.immix.ImmixConstants.*;

import org.mmtk.utility.Constants;
import org.mmtk.vm.VM;

import org.vmmagic.pragma.Inline;
import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.ObjectReference;
import org.vmmagic.unboxed.Offset;

@Uninterruptible
public class Line implements Constants {

  public static Address align(Address ptr) {
    return ptr.toWord().and(LINE_MASK.not()).toAddress();
  }

  public static boolean isAligned(Address address) {
    return address.EQ(align(address));
  }

  static int getChunkIndex(Address line) {
    return line.toWord().and(CHUNK_MASK).rshl(LOG_BYTES_IN_LINE).toInt();
  }

 /***************************************************************************
  * Line marking
  */
  static void mark(Address address, final byte markValue) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(Block.align(address)));
    getMarkAddress(address).store(markValue);
  }

  static void markMultiLine(Address start, ObjectReference object, final byte markValue) {
    /* endLine is the address of the last (highest) line touched by this object */
    Address endLine = Line.align(VM.objectModel.getObjectEndAddress(object).minus(1));
    Address line = Line.align(start.plus(BYTES_IN_LINE));
    while (line.LT(endLine)) {
      if (VM.VERIFY_ASSERTIONS)
        VM.assertions._assert(Block.align(start) == Block.align(line));
      mark(line, markValue);
      line = line.plus(BYTES_IN_LINE);
    }
  }

  /***************************************************************************
   * Scanning through avail lines
   */
  public static Address getChunkMarkTable(Address chunk) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
    return getMarkAddress(chunk);
  }

  public static Address getBlockMarkTable(Address block) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(block));
    return getMarkAddress(block);
  }

  @Inline
  public static int getNextUnavailable(Address baseLineAvailAddress, int line, final byte unavailableState) {
    while (line < LINES_IN_BLOCK &&
        baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS)) < unavailableState)
      line++;
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line <= LINES_IN_BLOCK);
    return line;
  }

  @Inline
  public static int getNextAvailable(Address baseLineAvailAddress, int line, final byte unavailableState) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line < LINES_IN_BLOCK);
    byte last = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS));
    byte thisline;
    line++;
    while (line < LINES_IN_BLOCK) {
      thisline = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS));
      if (thisline < unavailableState && last < unavailableState)
        break;
      last = thisline;
      line++;
    }
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line <= LINES_IN_BLOCK);
    return line;
  }

  private static Address getMetaAddress(Address address, final int tableOffset) {
    Address chunk = Chunk.align(address);
    int index = getChunkIndex(address);
    Address rtn = chunk.plus(tableOffset + (index<<LOG_BYTES_IN_LINE_STATUS));
    if (VM.VERIFY_ASSERTIONS) {
      Address line = chunk.plus(index<<LOG_BYTES_IN_LINE);
      VM.assertions._assert(isAligned(line));
      VM.assertions._assert(align(address).EQ(line));
      boolean valid = rtn.GE(chunk.plus(tableOffset)) && rtn.LT(chunk.plus(tableOffset + LINE_MARK_TABLE_BYTES));
      VM.assertions._assert(valid);
    }
    return rtn;
  }

  private static Address getMarkAddress(Address address) {
    return getMetaAddress(address, Chunk.LINE_MARK_TABLE_OFFSET);
  }

  /* per-line mark bytes */
  static final int LOG_BYTES_IN_LINE_STATUS = 0;
  static final int BYTES_IN_LINE_STATUS = 1<<LOG_BYTES_IN_LINE_STATUS;

  static final int LINE_MARK_TABLE_BYTES = LINES_IN_CHUNK<<LOG_BYTES_IN_LINE_STATUS;
  static final int LOG_LINE_MARK_BYTES_PER_BLOCK = LOG_LINES_IN_BLOCK+LOG_BYTES_IN_LINE_STATUS;
  static final int LINE_MARK_BYTES_PER_BLOCK = (1<<LOG_LINE_MARK_BYTES_PER_BLOCK);
}
