| /* |
| * 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)); |
| } |
| } |