/*
 *  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.utility.ForwardingWord;
import org.mmtk.utility.HeaderByte;
import org.mmtk.vm.VM;
import org.vmmagic.pragma.Inline;
import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.unboxed.ObjectReference;

@Uninterruptible
public class ObjectHeader {
  /** number of header bits we may use */
  static final int AVAILABLE_LOCAL_BITS = 8 - HeaderByte.USED_GLOBAL_BITS;

  /* header requirements */
  public static final int LOCAL_GC_BITS_REQUIRED = AVAILABLE_LOCAL_BITS;
  public static final int GLOBAL_GC_BITS_REQUIRED = 0;
  public static final int GC_HEADER_WORDS_REQUIRED = 0;

  /* local status bits */
  static final byte NEW_OBJECT_MARK = 0; // using zero means no need for explicit initialization on allocation

  public static final int PINNED_BIT_NUMBER = ForwardingWord.FORWARDING_BITS;
  public static final byte PINNED_BIT = 1<<PINNED_BIT_NUMBER;

  private static final int STRADDLE_BIT_NUMBER = PINNED_BIT_NUMBER + 1;
  public static final byte STRADDLE_BIT = 1<<STRADDLE_BIT_NUMBER;

  /* mark bits */
  private static final int  MARK_BASE = STRADDLE_BIT_NUMBER+1;
  static final int  MAX_MARKCOUNT_BITS = AVAILABLE_LOCAL_BITS-MARK_BASE;
  private static final byte MARK_INCREMENT = 1<<MARK_BASE;
  public static final byte MARK_MASK = (byte) (((1<<MAX_MARKCOUNT_BITS)-1)<<MARK_BASE);
  private static final byte MARK_AND_FORWARDING_MASK = (byte) (MARK_MASK | ForwardingWord.FORWARDING_MASK);
  public static final byte MARK_BASE_VALUE = MARK_INCREMENT;


  /****************************************************************************
   *
   * Marking
   */

  /**
   * Non-atomically test and set the mark bit of an object.  Return true
   * if successful, false if the mark bit was already set.
   *
   * @param object The object whose mark bit is to be written
   * @param markState The value to which the mark bits will be set
   */
  static byte testAndMark(ObjectReference object, byte markState) {
    byte oldValue, newValue, oldMarkState;

    oldValue = VM.objectModel.readAvailableByte(object);
    oldMarkState = (byte) (oldValue & MARK_MASK);
    if (oldMarkState != markState) {
      newValue = (byte) ((oldValue & ~MARK_MASK) | markState);
      if (HeaderByte.NEEDS_UNLOGGED_BIT)
        newValue |= HeaderByte.UNLOGGED_BIT;
      VM.objectModel.writeAvailableByte(object, newValue);
    }
    return oldMarkState;
  }

  static void setMarkStateUnlogAndUnlock(ObjectReference object, byte originalHeaderByte, byte markState) {
    byte oldValue = originalHeaderByte;
    byte newValue = (byte) ((oldValue & ~MARK_AND_FORWARDING_MASK) | markState);
    if (HeaderByte.NEEDS_UNLOGGED_BIT)
      newValue |= HeaderByte.UNLOGGED_BIT;
    VM.objectModel.writeAvailableByte(object, newValue);
    if (VM.VERIFY_ASSERTIONS)
      VM.assertions._assert((oldValue & MARK_MASK) != markState);
  }

  /**
   * Return true if the mark count for an object has the given value.
   *
   * @param object The object whose mark bit is to be tested
   * @param value The value against which the mark bit will be tested
   * @return True if the mark bit for the object has the given value.
   */
  static boolean testMarkState(ObjectReference object, byte value) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & MARK_MASK) == value);
    return (VM.objectModel.readAvailableByte(object) & MARK_MASK) == value;
   }

  static boolean testMarkState(byte forwardingWord, byte value) {
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & MARK_MASK) == value);
    return (forwardingWord & MARK_MASK) == value;
  }

  static boolean isNewObject(ObjectReference object) {
    return (VM.objectModel.readAvailableByte(object) & MARK_AND_FORWARDING_MASK) == NEW_OBJECT_MARK;
  }

  static boolean isMatureObject(ObjectReference object) {
    byte status = (byte) (VM.objectModel.readAvailableByte(object) & MARK_AND_FORWARDING_MASK);
    boolean unforwarded = (status & ForwardingWord.FORWARDING_MASK) == 0;
    boolean newObj = (status == NEW_OBJECT_MARK);
    return unforwarded && !newObj;
  }

  @Inline
  static void markAsStraddling(ObjectReference object) {
    byte old = VM.objectModel.readAvailableByte(object);
    VM.objectModel.writeAvailableByte(object, (byte) (old | STRADDLE_BIT));
  }

  @Inline
  static boolean isStraddlingObject(ObjectReference object) {
    return (VM.objectModel.readAvailableByte(object) & STRADDLE_BIT) == STRADDLE_BIT;
  }

  @Inline
  public static void pinObject(ObjectReference object) {
    byte old = VM.objectModel.readAvailableByte(object);
    VM.objectModel.writeAvailableByte(object, (byte) (old | PINNED_BIT));
  }

  @Inline
  static boolean isPinnedObject(ObjectReference object) {
    return (VM.objectModel.readAvailableByte(object) & PINNED_BIT) == PINNED_BIT;
  }

  /**
   * Write the allocState into the mark state fields of an object non-atomically.
   * This is appropriate for collection time initialization.
   *
   * @param object The object whose mark state is to be written
   * @param markState TODO: what am I?
   * @param straddle TODO: what am I?
   */
  static void writeMarkState(ObjectReference object, byte markState, boolean straddle) {
    byte oldValue = VM.objectModel.readAvailableByte(object);
    byte markValue = markState;
    byte newValue = (byte) (oldValue & ~MARK_AND_FORWARDING_MASK);
    if (HeaderByte.NEEDS_UNLOGGED_BIT)
      newValue |= HeaderByte.UNLOGGED_BIT;
    newValue |= markValue;
    if (straddle)
      newValue |= STRADDLE_BIT;
    VM.objectModel.writeAvailableByte(object, newValue);
  }

  static void returnToPriorStateAndEnsureUnlogged(ObjectReference object, byte status) {
    if (HeaderByte.NEEDS_UNLOGGED_BIT) status |= HeaderByte.UNLOGGED_BIT;
    VM.objectModel.writeAvailableByte(object, status);
  }

  /**
   * Return the mark state incremented or decremented by one.
   *
   * @param increment If true, then return the incremented value else return the decremented value
   * @return the mark state incremented or decremented by one.
   */
  static byte deltaMarkState(byte state, boolean increment) {
    byte rtn = state;
    do {
      rtn = (byte) (increment ? rtn + MARK_INCREMENT : rtn - MARK_INCREMENT);
      rtn &= MARK_MASK;
      } while (rtn < MARK_BASE_VALUE);
    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn != state);
    return rtn;
  }
}
