/*
 *  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.j3.mmtk;

import org.jikesrvm.SizeConstants;
import org.jikesrvm.Magic;
import org.j3.runtime.VM;

import org.vmmagic.unboxed.*;
import org.vmmagic.pragma.*;

@Uninterruptible
public class Barriers extends org.mmtk.vm.Barriers implements SizeConstants {
  /**
   * Perform the actual write of a boolean write barrier.
   *
   * @param objref The object that has the boolean field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The FieldReference index to assist the store
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void booleanWrite(ObjectReference objref, boolean value, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setBooleanAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
  }

  /**
   * Perform the actual read of a boolean read barrier.
   *
   * @param objref The object that has the boolean field
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final boolean booleanRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getByteAtOffset(objref.toObject(), offset.toOffset()) == 0;
  }

  /**
   * Perform the actual write of a byte write barrier.
   *
   * @param objref The object that has the byte field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The FieldReference index to assist the store
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void byteWrite(ObjectReference objref, byte value, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setByteAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
  }

  /**
   * Perform the actual read of a byte read barrier.
   *
   * @param objref The object that has the byte field
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final byte byteRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getByteAtOffset(objref.toObject(), offset.toOffset());
  }

  /**
   * Perform the actual write of a char write barrier.
   *
   * @param objref The object that has the char field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The FieldReference index to assist the store
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void charWrite(ObjectReference objref, char value, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setCharAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
  }

  /**
   * Perform the actual read of a char read barrier.
   *
   * @param objref The object that has the char field
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final char charRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getCharAtOffset(objref.toObject(), offset.toOffset());
  }

  /**
   * Perform the actual write of a short write barrier.
   *
   * @param objref The object that has the short field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The FieldReference index to assist the store
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void shortWrite(ObjectReference objref, short value, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setShortAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
  }

  /**
   * Perform the actual read of a short read barrier.
   *
   * @param objref The object that has the short field
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final short shortRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getShortAtOffset(objref.toObject(), offset.toOffset());
  }

  /**
   * Perform the actual write of a int write barrier.
   *
   * @param objref The object that has the int field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The FieldReference index to assist the store
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void intWrite(ObjectReference objref, int value, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setIntAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
  }

  /**
   * Perform the actual read of a int read barrier.
   *
   * @param objref The object that has the int field
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final int intRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getIntAtOffset(objref.toObject(), offset.toOffset());
  }

  /**
   * Attempt an atomic compare and exchange in a write barrier sequence.
   *
   * @param objref The object that has the int field
   * @param expected The old int to be swapped out
   * @param newValue the new int
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return True if the compare and swap was successful
   */
  @Override
  public boolean intTryCompareAndSwap(ObjectReference objref, int expected, int newValue, Word offset, Word unused, int mode) {
    VM._assert(VM.NOT_REACHED);
    int oldValue;
    do {
      oldValue = Magic.prepareInt(objref, offset.toOffset());
      if (oldValue != expected) return false;
    } while (!Magic.attemptInt(objref, offset.toOffset(), oldValue, newValue));
    return true;
  }

  /**
   * Perform the actual write of a long write barrier.
   *
   * @param objref The object that has the long field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The FieldReference index to assist the store
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void longWrite(ObjectReference objref, long value, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setLongAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
  }

  /**
   * Perform the actual read of a long read barrier.
   *
   * @param objref The object that has the long field
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final long longRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getLongAtOffset(objref.toObject(), offset.toOffset());
  }

  /**
   * Attempt an atomic compare and exchange in a write barrier sequence.
   *
   * @param objref The object that has the long field
   * @param expected The old long to be swapped out
   * @param newValue the new long
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return True if the compare and swap was successful
   */
  @Override
  public boolean longTryCompareAndSwap(ObjectReference objref, long expected, long newValue, Word offset, Word unused, int mode) {
    VM._assert(VM.NOT_REACHED);
    long oldValue;
    do {
      oldValue = Magic.prepareLong(objref, offset.toOffset());
      if (oldValue != expected) return false;
    } while (!Magic.attemptLong(objref, offset.toOffset(), oldValue, newValue));
    return true;
  }

  /**
   * Perform the actual write of a float write barrier.
   *
   * @param objref The object that has the float field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The FieldReference index to assist the store
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void floatWrite(ObjectReference objref, float value, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setFloatAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
  }

  /**
   * Perform the actual read of a float read barrier.
   *
   * @param objref The object that has the float field
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final float floatRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getFloatAtOffset(objref.toObject(), offset.toOffset());
  }

  /**
   * Perform the actual write of a double write barrier.
   *
   * @param objref The object that has the double field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The FieldReference index to assist the store
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void doubleWrite(ObjectReference objref, double value, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setDoubleAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
  }

  /**
   * Perform the actual read of a double read barrier.
   *
   * @param objref The object that has the double field
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final double doubleRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getDoubleAtOffset(objref.toObject(), offset.toOffset());
  }

  /**
   * Perform the actual write of an object reference write barrier.
   *
   * @param objref The object that has the reference field
   * @param value The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void objectReferenceWrite(ObjectReference objref, ObjectReference value, Word slot, Word location, int mode) {
    slot.toAddress().store(value);
  }

  /**
   * Perform the actual read of an object reference read barrier.
   *
   * @param objref The object that has the reference field
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   * @return the object reference read value
   */
  @Inline
  @Override
  public final ObjectReference objectReferenceRead(ObjectReference objref, Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return ObjectReference.fromObject(Magic.getObjectAtOffset(objref.toObject(), offset.toOffset(), location.toInt()));
  }

  /**
   * Perform the actual write of the non-heap write barrier.  This is
   * used when the store is not to an object, but to a non-heap location
   * such as statics or the stack.
   * @param target The value that the slot will be updated to
   * @param unusedA The offset from the ref
   * @param unusedB Unused
   * @param ref The object that has the reference field
   */
  @Inline
  @Override
  public final void objectReferenceNonHeapWrite(Address slot, ObjectReference target, Word unusedA, Word unusedB) {
    slot.store(target);
  }

  /**
   * Atomically write a reference field of an object or array and return
   * the old value of the reference field.
   *
   * @param objref The object that has the reference field
   * @param target The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return The value that was replaced by the write.
   */
  @Inline
  @Override
  public final ObjectReference objectReferenceAtomicWrite(ObjectReference objref, ObjectReference target, Word offset, Word unused, int mode) {
    VM._assert(VM.NOT_REACHED);
    Object obj = objref.toObject();
    Object newObject = target.toObject();
    Object oldObject;
    do {
      oldObject = Magic.prepareObject(obj, offset.toOffset());
    } while (!Magic.attemptObject(obj, offset.toOffset(), oldObject, newObject));
    return ObjectReference.fromObject(oldObject);
  }

  /**
   * Attempt an atomic compare and exchange in a write barrier sequence.
   *
   * @param objref The object that has the reference field
   * @param old The old reference to be swapped out
   * @param target The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return True if the compare and swap was successful
   */
  @Inline
  @Override
  public final boolean objectReferenceTryCompareAndSwap(ObjectReference objref, ObjectReference old, ObjectReference target, Word offset, Word unused, int mode) {
    VM._assert(VM.NOT_REACHED);
    Object oldValue;
    do {
      oldValue = Magic.prepareObject(objref, offset.toOffset());
      if (oldValue != old) return false;
    } while (!Magic.attemptObject(objref, offset.toOffset(), oldValue, target));
    return true;
  }

  /**
   * Perform the actual write of the write barrier, writing the value as a raw Word.
   *
   * @param ref The object that has the Word field
   * @param target The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void wordWrite(ObjectReference ref, Word target,
      Word slot, Word location, int mode) {
    slot.toAddress().store(target);
  }

  /**
   * Atomically write a raw reference field of an object or array and return
   * the old value of the reference field.
   *
   * @param ref The object that has the Word field
   * @param target The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return The value that was replaced by the write.
   */
  @Inline
  @Override
  public final Word wordAtomicWrite(ObjectReference ref, Word target,
      Word offset, Word unused, int mode) {
    VM._assert(VM.NOT_REACHED);
    Word oldValue;
    do {
      oldValue = Magic.prepareWord(ref.toObject(), offset.toOffset());
    } while (!Magic.attemptWord(ref.toObject(), offset.toOffset(), oldValue, target));
    return oldValue;
  }

  /**
   * Attempt an atomic compare and exchange in a write barrier sequence.
   *
   * @param ref The object that has the Word field
   * @param old The old Word to be swapped out
   * @param target The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return True if the compare and swap was successful
   */
  @Inline
  @Override
  public final boolean wordTryCompareAndSwap(ObjectReference ref, Word old, Word target,
      Word offset, Word unused, int mode) {
    VM._assert(VM.NOT_REACHED);
    do {
      Word currentValue = Magic.prepareWord(ref, offset.toOffset());
      if (currentValue != old) return false;
    } while (!Magic.attemptWord(ref, offset.toOffset(), old, target));
    return true;
  }

  /**
   * Perform the actual read of the read barrier, returning the value as a raw Word.
   *
   * @param ref The object that has the Word field
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final Word wordRead(ObjectReference ref,
        Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getWordAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
  }

  /**
   * Perform the actual write of the write barrier, writing the value as a raw Address.
   *
   * @param ref The object that has the Address field
   * @param target The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void addressWrite(ObjectReference ref, Address target,
      Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setAddressAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
  }

  /**
   * Perform the actual read of the read barrier, returning the value as a raw Address.
   *
   * @param ref The object that has the Address field
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final Address addressRead(ObjectReference ref,
        Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getAddressAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
  }

  /**
   * Attempt an atomic compare and exchange in a write barrier sequence.
   *
   * @param objref The object that has the Address field
   * @param expected The old Address to be swapped out
   * @param newValue the new Address
   * @param offset The offset from the ref
   * @param unused Unused
   * @param mode The context in which the write is occurring
   * @return True if the compare and swap was successful
   */
  @Override
  public boolean addressTryCompareAndSwap(ObjectReference objref, Address expected, Address newValue, Word offset, Word unused, int mode) {
    VM._assert(VM.NOT_REACHED);
    Address oldValue;
    do {
      oldValue = Magic.prepareAddress(objref, offset.toOffset());
      if (oldValue != expected) return false;
    } while (!Magic.attemptAddress(objref, offset.toOffset(), oldValue, newValue));
    return true;
  }

  /**
   * Perform the actual write of the write barrier, writing the value as a raw Offset.
   *
   * @param ref The object that has the Offset field
   * @param target The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void offsetWrite(ObjectReference ref, Offset target,
      Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setOffsetAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
  }

  /**
   * Perform the actual read of the read barrier, returning the value as a raw Offset.
   *
   * @param ref The object that has the Offset field
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final Offset offsetRead(ObjectReference ref,
        Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getOffsetAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
  }

  /**
   * Perform the actual write of the write barrier, writing the value as a raw Extent.
   *
   * @param ref The object that has the Extent field
   * @param target The value that the slot will be updated to
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   */
  @Inline
  @Override
  public final void extentWrite(ObjectReference ref, Extent target,
      Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    Magic.setExtentAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
  }

  /**
   * Perform the actual read of the read barrier, returning the value as a raw Extent.
   *
   * @param ref The object that has the Extent field
   * @param offset The offset from the ref
   * @param location The index of the FieldReference
   * @param mode The context in which the write is occurring
   * @return the read value
   */
  @Inline
  @Override
  public final Extent extentRead(ObjectReference ref,
        Word offset, Word location, int mode) {
    VM._assert(VM.NOT_REACHED);
    return Magic.getExtentAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
  }

  /**
   * Sets an element of an object array without invoking any write
   * barrier.  This method is called by the Map class to ensure
   * potentially-allocation-triggering write barriers do not occur in
   * allocation slow path code.
   *
   * @param dst the destination array
   * @param index the index of the element to set
   * @param value the new value for the element
   */
  @UninterruptibleNoWarn
  @Override
  public final void objectArrayStoreNoGCBarrier(Object[] dst, int index, Object value) {
    dst[index] = value;
    // TODO(ngeoffray): I don't think this is needed, the previous statement should not have
    // had a GC barrier.
    //
    // Address base = ObjectReference.fromObject(dst).toAddress();
    // Add 3 for the header, the class, and the length.
    // Address slot = base.plus(Offset.fromIntZeroExtend((index + 3) << LOG_BYTES_IN_ADDRESS));
    // VM.activePlan.global().storeObjectReference(slot, ObjectReference.fromObject(value));
  }
}
