/* * 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.jikesrvm.mm.mminterface; import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_BOOLEAN; import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_DOUBLE; import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_FLOAT; import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_LONG; import static org.mmtk.utility.Constants.ARRAY_ELEMENT; import static org.mmtk.utility.Constants.INSTANCE_FIELD; import static org.mmtk.utility.Constants.LOG_BYTES_IN_ADDRESS; import static org.mmtk.utility.Constants.LOG_BYTES_IN_CHAR; import static org.mmtk.utility.Constants.LOG_BYTES_IN_INT; import static org.mmtk.utility.Constants.LOG_BYTES_IN_SHORT; import org.jikesrvm.VM; import org.jikesrvm.runtime.Magic; import org.jikesrvm.runtime.Memory; import org.vmmagic.pragma.Entrypoint; import org.vmmagic.pragma.Inline; 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; @Uninterruptible public class Barriers { /** {@code true} if the selected plan requires a read barrier on java.lang.ref.Reference types */ private static final boolean NEEDS_JAVA_LANG_REFERENCE_GC_READ_BARRIER = Selected.Constraints.get().needsJavaLangReferenceReadBarrier(); /** {@code true} if the selected plan requires a read barrier on java.lang.ref.Reference types */ public static final boolean NEEDS_JAVA_LANG_REFERENCE_READ_BARRIER = NEEDS_JAVA_LANG_REFERENCE_GC_READ_BARRIER; /** * A java.lang.ref.Reference is being read. * * @param obj The non-null referent about to be released to the mutator. * @return The object to release to the mutator. */ public static Object javaLangReferenceReadBarrier(Object obj) { if (NEEDS_JAVA_LANG_REFERENCE_GC_READ_BARRIER) { ObjectReference result = Selected.Mutator.get().javaLangReferenceReadBarrier(ObjectReference.fromObject(obj)); return result.toObject(); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return null; } /* bool byte char short int long float double */ /** {@code true} if the garbage collector requires write barriers on boolean putfield, arraystore or modifycheck */ private static final boolean NEEDS_BOOLEAN_GC_WRITE_BARRIER = Selected.Constraints.get().needsBooleanWriteBarrier(); /** {@code true} if the VM requires write barriers on boolean putfield */ public static final boolean NEEDS_BOOLEAN_PUTFIELD_BARRIER = NEEDS_BOOLEAN_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on boolean arraystore */ public static final boolean NEEDS_BOOLEAN_ASTORE_BARRIER = NEEDS_BOOLEAN_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on boolean getfield or arrayload */ private static final boolean NEEDS_BOOLEAN_GC_READ_BARRIER = Selected.Constraints.get().needsBooleanReadBarrier(); /** {@code true} if the VM requires read barriers on boolean getfield */ public static final boolean NEEDS_BOOLEAN_GETFIELD_BARRIER = NEEDS_BOOLEAN_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on boolean arrayload */ public static final boolean NEEDS_BOOLEAN_ALOAD_BARRIER = NEEDS_BOOLEAN_GC_READ_BARRIER; /** {@code true} if the garbage collector does not support the bulk copy operation */ public static final boolean BOOLEAN_BULK_COPY_SUPPORTED = !(NEEDS_BOOLEAN_ASTORE_BARRIER || NEEDS_BOOLEAN_ALOAD_BARRIER) || Selected.Constraints.get().booleanBulkCopySupported(); /** * Barrier for writes of booleans into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void booleanFieldWrite(Object ref, boolean value, Offset offset, int locationMetadata) { if (NEEDS_BOOLEAN_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().booleanWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of booleans into arrays (i.e. bastore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void booleanArrayWrite(boolean[] ref, int index, boolean value) { if (NEEDS_BOOLEAN_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_BOOLEAN); Selected.Mutator.get().booleanWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of booleans from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static boolean booleanFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_BOOLEAN_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().booleanRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return false; } /** * Barrier for loads of booleans from fields of arrays (i.e. aload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static boolean booleanArrayRead(boolean[] ref, int index) { if (NEEDS_BOOLEAN_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_BOOLEAN); return Selected.Mutator.get().booleanRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return false; } /** * Barrier for a bulk copy of booleans (i.e. in an array copy). * * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void booleanBulkCopy(boolean[] src, Offset srcOffset, boolean[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(BOOLEAN_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().booleanBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.aligned8Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /** {@code true} if the garbage collector requires write barriers on byte putfield, arraystore or modifycheck */ private static final boolean NEEDS_BYTE_GC_WRITE_BARRIER = Selected.Constraints.get().needsByteWriteBarrier(); /** {@code true} if the VM requires write barriers on byte putfield */ public static final boolean NEEDS_BYTE_PUTFIELD_BARRIER = NEEDS_BYTE_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on byte arraystore */ public static final boolean NEEDS_BYTE_ASTORE_BARRIER = NEEDS_BYTE_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on byte getfield or arrayload */ private static final boolean NEEDS_BYTE_GC_READ_BARRIER = Selected.Constraints.get().needsByteReadBarrier(); /** {@code true} if the VM requires read barriers on byte getfield */ public static final boolean NEEDS_BYTE_GETFIELD_BARRIER = NEEDS_BYTE_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on byte arrayload */ public static final boolean NEEDS_BYTE_ALOAD_BARRIER = NEEDS_BYTE_GC_READ_BARRIER; /** {@code true} if the garbage collector does not support the bulk copy operation */ public static final boolean BYTE_BULK_COPY_SUPPORTED = !(NEEDS_BYTE_ASTORE_BARRIER || NEEDS_BYTE_ALOAD_BARRIER) || Selected.Constraints.get().byteBulkCopySupported(); /** * Barrier for writes of bytes into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void byteFieldWrite(Object ref, byte value, Offset offset, int locationMetadata) { if (NEEDS_BYTE_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().byteWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of bytes into arrays (i.e. bastore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void byteArrayWrite(byte[] ref, int index, byte value) { if (NEEDS_BYTE_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index); Selected.Mutator.get().byteWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of bytes from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static byte byteFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_BYTE_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().byteRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for loads of bytes from fields of arrays (i.e. baload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static byte byteArrayRead(byte[] ref, int index) { if (NEEDS_BYTE_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index); return Selected.Mutator.get().byteRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for a bulk copy of bytes (i.e. in an array copy). * * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void byteBulkCopy(byte[] src, Offset srcOffset, byte[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(BYTE_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().byteBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.aligned8Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /** {@code true} if the garbage collector requires write barriers on char putfield, arraystore or modifycheck */ private static final boolean NEEDS_CHAR_GC_WRITE_BARRIER = Selected.Constraints.get().needsCharWriteBarrier(); /** {@code true} if the VM requires write barriers on char putfield */ public static final boolean NEEDS_CHAR_PUTFIELD_BARRIER = NEEDS_CHAR_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on char arraystore */ public static final boolean NEEDS_CHAR_ASTORE_BARRIER = NEEDS_CHAR_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on char getfield or arrayload */ private static final boolean NEEDS_CHAR_GC_READ_BARRIER = Selected.Constraints.get().needsCharReadBarrier(); /** {@code true} if the VM requires read barriers on char getfield */ public static final boolean NEEDS_CHAR_GETFIELD_BARRIER = NEEDS_CHAR_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on char arrayload */ public static final boolean NEEDS_CHAR_ALOAD_BARRIER = NEEDS_CHAR_GC_READ_BARRIER; /** {@code true} if the garbage collector does not support the bulk copy operation */ public static final boolean CHAR_BULK_COPY_SUPPORTED = !(NEEDS_CHAR_ASTORE_BARRIER || NEEDS_CHAR_ALOAD_BARRIER) || Selected.Constraints.get().charBulkCopySupported(); /** * Barrier for writes of chars into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void charFieldWrite(Object ref, char value, Offset offset, int locationMetadata) { if (NEEDS_CHAR_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().charWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of chars into arrays (i.e. castore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void charArrayWrite(char[] ref, int index, char value) { if (NEEDS_CHAR_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR); Selected.Mutator.get().charWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of chars from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static char charFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_CHAR_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().charRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for loads of chars from fields of arrays (i.e. caload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static char charArrayRead(char[] ref, int index) { if (NEEDS_CHAR_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR); return Selected.Mutator.get().charRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for a bulk copy of chars (i.e. in an array copy). * * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void charBulkCopy(char[] src, Offset srcOffset, char[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(CHAR_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().charBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.aligned16Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /** {@code true} if the garbage collector requires write barriers on short putfield, arraystore or modifycheck */ private static final boolean NEEDS_SHORT_GC_WRITE_BARRIER = Selected.Constraints.get().needsShortWriteBarrier(); /** {@code true} if the VM requires write barriers on short putfield */ public static final boolean NEEDS_SHORT_PUTFIELD_BARRIER = NEEDS_SHORT_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on short arraystore */ public static final boolean NEEDS_SHORT_ASTORE_BARRIER = NEEDS_SHORT_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on short getfield or arrayload */ private static final boolean NEEDS_SHORT_GC_READ_BARRIER = Selected.Constraints.get().needsShortReadBarrier(); /** {@code true} if the VM requires read barriers on short getfield */ public static final boolean NEEDS_SHORT_GETFIELD_BARRIER = NEEDS_SHORT_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on short arrayload */ public static final boolean NEEDS_SHORT_ALOAD_BARRIER = NEEDS_SHORT_GC_READ_BARRIER; /** {@code true} if the garbage collector does not support the bulk copy operation */ public static final boolean SHORT_BULK_COPY_SUPPORTED = !(NEEDS_SHORT_ASTORE_BARRIER || NEEDS_SHORT_ALOAD_BARRIER) || Selected.Constraints.get().shortBulkCopySupported(); /** * Barrier for writes of shorts into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void shortFieldWrite(Object ref, short value, Offset offset, int locationMetadata) { if (NEEDS_SHORT_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().shortWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of shorts into arrays (i.e. sastore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void shortArrayWrite(short[] ref, int index, short value) { if (NEEDS_SHORT_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_SHORT); Selected.Mutator.get().shortWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of shorts from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static short shortFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_SHORT_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().shortRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for loads of shorts from fields of arrays (i.e. saload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static short shortArrayRead(short[] ref, int index) { if (NEEDS_SHORT_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_SHORT); return Selected.Mutator.get().shortRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for a bulk copy of shorts (i.e. in an array copy). * * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void shortBulkCopy(short[] src, Offset srcOffset, short[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(SHORT_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().shortBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.aligned16Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /** {@code true} if the garbage collector requires write barriers on int putfield, arraystore or modifycheck */ private static final boolean NEEDS_INT_GC_WRITE_BARRIER = Selected.Constraints.get().needsIntWriteBarrier(); /** {@code true} if the VM requires write barriers on int putfield */ public static final boolean NEEDS_INT_PUTFIELD_BARRIER = NEEDS_INT_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on int arraystore */ public static final boolean NEEDS_INT_ASTORE_BARRIER = NEEDS_INT_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on int getfield or arrayload */ private static final boolean NEEDS_INT_GC_READ_BARRIER = Selected.Constraints.get().needsIntReadBarrier(); /** {@code true} if the VM requires read barriers on int getfield */ public static final boolean NEEDS_INT_GETFIELD_BARRIER = NEEDS_INT_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on int arrayload */ public static final boolean NEEDS_INT_ALOAD_BARRIER = NEEDS_INT_GC_READ_BARRIER; /** {@code true} if the garbage collector does not support the bulk copy operation */ public static final boolean INT_BULK_COPY_SUPPORTED = !(NEEDS_INT_ASTORE_BARRIER || NEEDS_INT_ALOAD_BARRIER) || Selected.Constraints.get().intBulkCopySupported(); /** * Barrier for writes of ints into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void intFieldWrite(Object ref, int value, Offset offset, int locationMetadata) { if (NEEDS_INT_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().intWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of ints into arrays (i.e. iastore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void intArrayWrite(int[] ref, int index, int value) { if (NEEDS_INT_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_INT); Selected.Mutator.get().intWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of ints from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static int intFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_INT_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().intRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for loads of ints from fields of arrays (i.e. iaload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static int intArrayRead(int[] ref, int index) { if (NEEDS_INT_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_INT); return Selected.Mutator.get().intRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for a bulk copy of ints (i.e. in an array copy). * * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void intBulkCopy(int[] src, Offset srcOffset, int[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(INT_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().intBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.aligned32Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /** * Barrier for conditional compare and exchange of int fields. * @param ref the object which is the subject of the compare and exchanges * @param offset the offset of the field to be modified * @param old the old value to swap out * @param value the new value for the field * @return {@code true} if and only if the swap was successful */ @Inline public static boolean intTryCompareAndSwap(Object ref, Offset offset, int old, int value) { if (NEEDS_INT_GC_WRITE_BARRIER || NEEDS_INT_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().intTryCompareAndSwap(src, src.toAddress().plus(offset), old, value, offset.toWord(), Word.zero(), // do not have location metadata INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return false; } /** {@code true} if the garbage collector requires write barriers on long putfield, arraystore or modifycheck */ private static final boolean NEEDS_LONG_GC_WRITE_BARRIER = Selected.Constraints.get().needsLongWriteBarrier(); /** {@code true} if the VM requires write barriers on long putfield */ public static final boolean NEEDS_LONG_PUTFIELD_BARRIER = NEEDS_LONG_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on long arraystore */ public static final boolean NEEDS_LONG_ASTORE_BARRIER = NEEDS_LONG_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on long getfield or arrayload */ private static final boolean NEEDS_LONG_GC_READ_BARRIER = Selected.Constraints.get().needsLongReadBarrier(); /** {@code true} if the VM requires read barriers on long getfield */ public static final boolean NEEDS_LONG_GETFIELD_BARRIER = NEEDS_LONG_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on long arrayload */ public static final boolean NEEDS_LONG_ALOAD_BARRIER = NEEDS_LONG_GC_READ_BARRIER; /** {@code true} if the garbage collector supports the bulk copy operation */ public static final boolean LONG_BULK_COPY_SUPPORTED = !(NEEDS_LONG_ASTORE_BARRIER || NEEDS_LONG_ALOAD_BARRIER) || Selected.Constraints.get().longBulkCopySupported(); /** * Barrier for writes of longs into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void longFieldWrite(Object ref, long value, Offset offset, int locationMetadata) { if (NEEDS_LONG_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().longWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of longs into arrays (i.e. lastore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void longArrayWrite(long[] ref, int index, long value) { if (NEEDS_LONG_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_LONG); Selected.Mutator.get().longWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of longs from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static long longFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_LONG_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().longRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for loads of longs from fields of arrays (i.e. laload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static long longArrayRead(long[] ref, int index) { if (NEEDS_LONG_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_LONG); return Selected.Mutator.get().longRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for conditional compare and exchange of long fields. * @param ref the object which is the subject of the compare and exchanges * @param offset the offset of the field to be modified * @param old the old value to swap out * @param value the new value for the field * @return {@code true} if and only if the swap was successful */ @Inline public static boolean longTryCompareAndSwap(Object ref, Offset offset, long old, long value) { if (NEEDS_LONG_GC_WRITE_BARRIER || NEEDS_LONG_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().longTryCompareAndSwap(src, src.toAddress().plus(offset), old, value, offset.toWord(), Word.zero(), // do not have location metadata INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return false; } /** * Barrier for a bulk copy of longs (i.e. in an array copy). * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void longBulkCopy(long[] src, Offset srcOffset, long[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(LONG_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().longBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.aligned64Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /** {@code true} if the garbage collector requires write barriers on float putfield, arraystore or modifycheck */ private static final boolean NEEDS_FLOAT_GC_WRITE_BARRIER = Selected.Constraints.get().needsFloatWriteBarrier(); /** {@code true} if the VM requires write barriers on float putfield */ public static final boolean NEEDS_FLOAT_PUTFIELD_BARRIER = NEEDS_FLOAT_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on float arraystore */ public static final boolean NEEDS_FLOAT_ASTORE_BARRIER = NEEDS_FLOAT_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on float getfield or arrayload */ private static final boolean NEEDS_FLOAT_GC_READ_BARRIER = Selected.Constraints.get().needsFloatReadBarrier(); /** {@code true} if the VM requires read barriers on float getfield */ public static final boolean NEEDS_FLOAT_GETFIELD_BARRIER = NEEDS_FLOAT_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on float arrayload */ public static final boolean NEEDS_FLOAT_ALOAD_BARRIER = NEEDS_FLOAT_GC_READ_BARRIER; /** {@code true} if the garbage collector supports the bulk copy operation */ public static final boolean FLOAT_BULK_COPY_SUPPORTED = !(NEEDS_FLOAT_ASTORE_BARRIER || NEEDS_FLOAT_ALOAD_BARRIER) || Selected.Constraints.get().floatBulkCopySupported(); /** * Barrier for writes of floats into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void floatFieldWrite(Object ref, float value, Offset offset, int locationMetadata) { if (NEEDS_FLOAT_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().floatWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of floats into arrays (i.e. fastore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void floatArrayWrite(float[] ref, int index, float value) { if (NEEDS_FLOAT_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT); Selected.Mutator.get().floatWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of floats from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static float floatFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_FLOAT_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().floatRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for loads of floats from fields of arrays (i.e. faload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static float floatArrayRead(float[] ref, int index) { if (NEEDS_FLOAT_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT); return Selected.Mutator.get().floatRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for a bulk copy of floats (i.e. in an array copy). * * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void floatBulkCopy(float[] src, Offset srcOffset, float[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(FLOAT_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().floatBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.aligned32Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /** {@code true} if the garbage collector requires write barriers on double putfield, arraystore or modifycheck */ private static final boolean NEEDS_DOUBLE_GC_WRITE_BARRIER = Selected.Constraints.get().needsDoubleWriteBarrier(); /** {@code true} if the VM requires write barriers on double putfield */ public static final boolean NEEDS_DOUBLE_PUTFIELD_BARRIER = NEEDS_DOUBLE_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on double arraystore */ public static final boolean NEEDS_DOUBLE_ASTORE_BARRIER = NEEDS_DOUBLE_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on double getfield or arrayload */ private static final boolean NEEDS_DOUBLE_GC_READ_BARRIER = Selected.Constraints.get().needsDoubleReadBarrier(); /** {@code true} if the VM requires read barriers on double getfield */ public static final boolean NEEDS_DOUBLE_GETFIELD_BARRIER = NEEDS_DOUBLE_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on double arrayload */ public static final boolean NEEDS_DOUBLE_ALOAD_BARRIER = NEEDS_DOUBLE_GC_READ_BARRIER; /** {@code true} if the garbage collector supports the bulk copy operation */ public static final boolean DOUBLE_BULK_COPY_SUPPORTED = !(NEEDS_DOUBLE_ASTORE_BARRIER || NEEDS_DOUBLE_ALOAD_BARRIER) || Selected.Constraints.get().doubleBulkCopySupported(); /** * Barrier for writes of doubles into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void doubleFieldWrite(Object ref, double value, Offset offset, int locationMetadata) { if (NEEDS_DOUBLE_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().doubleWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of doubles into arrays (i.e. dastore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void doubleArrayWrite(double[] ref, int index, double value) { if (NEEDS_DOUBLE_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_DOUBLE); Selected.Mutator.get().doubleWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of doubles from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static double doubleFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_DOUBLE_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().doubleRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for loads of doubles from fields of arrays (i.e. daload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static double doubleArrayRead(double[] ref, int index) { if (NEEDS_DOUBLE_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_DOUBLE); return Selected.Mutator.get().doubleRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return 0; } /** * Barrier for a bulk copy of doubles (i.e. in an array copy). * * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void doubleBulkCopy(double[] src, Offset srcOffset, double[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(DOUBLE_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().doubleBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.aligned64Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /******************************************************************************** * Begin support for org.vmmagic.unboxed types (Word, Address, Extent and Offset) * * These types can be witten or read from Object fields via putfield and getfield * Arrays of these special types should not be created in the normal Java way * (i.e. new Word[]) but should be created using WordArray.create() etc. * * TODO: is there a RVM mechanism that prevents new Word[]? */ /** {@code true} if the garbage collector requires write barriers on Word putfield, arraystore or modifycheck */ private static final boolean NEEDS_WORD_GC_WRITE_BARRIER = Selected.Constraints.get().needsWordWriteBarrier(); /** {@code true} if the VM requires write barriers on Word putfield */ public static final boolean NEEDS_WORD_PUTFIELD_BARRIER = NEEDS_WORD_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on Word getfield or arrayload */ private static final boolean NEEDS_WORD_GC_READ_BARRIER = Selected.Constraints.get().needsWordReadBarrier(); /** {@code true} if the VM requires read barriers on Word getfield */ public static final boolean NEEDS_WORD_GETFIELD_BARRIER = NEEDS_WORD_GC_READ_BARRIER; /** * Barrier for writes of Words into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void wordFieldWrite(Object ref, Word value, Offset offset, int locationMetadata) { if (NEEDS_WORD_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().wordWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of Words from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static Word wordFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_WORD_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().wordRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return Word.zero(); } /** * Barrier for conditional compare and exchange of Word fields. * * @param ref the object which is the subject of the compare and exchanges * @param offset the offset of the field to be modified * @param old the old value to swap out * @param value the new value for the field * @return {@code true} if and only if the swap was successful */ @Inline public static boolean wordTryCompareAndSwap(Object ref, Offset offset, Word old, Word value) { if (NEEDS_WORD_GC_WRITE_BARRIER || NEEDS_WORD_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().wordTryCompareAndSwap(src, src.toAddress().plus(offset), old, value, offset.toWord(), Word.zero(), // do not have location metadata INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return false; } /** {@code true} if the garbage collector requires write barriers on Address putfield, arraystore or modifycheck */ private static final boolean NEEDS_ADDRESS_GC_WRITE_BARRIER = Selected.Constraints.get().needsAddressWriteBarrier(); /** {@code true} if the VM requires write barriers on Address putfield */ public static final boolean NEEDS_ADDRESS_PUTFIELD_BARRIER = NEEDS_ADDRESS_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on Address getfield or arrayload */ private static final boolean NEEDS_ADDRESS_GC_READ_BARRIER = Selected.Constraints.get().needsAddressReadBarrier(); /** {@code true} if the VM requires read barriers on Address getfield */ public static final boolean NEEDS_ADDRESS_GETFIELD_BARRIER = NEEDS_ADDRESS_GC_READ_BARRIER; /** * Barrier for writes of Address's into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void addressFieldWrite(Object ref, Address value, Offset offset, int locationMetadata) { if (NEEDS_ADDRESS_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().addressWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of Address's from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static Address addressFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_ADDRESS_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().addressRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return Address.zero(); } /** * Barrier for conditional compare and exchange of Address fields. * * @param ref the object which is the subject of the compare and exchanges * @param offset the offset of the field to be modified * @param old the old value to swap out * @param value the new value for the field * @return {@code true} if and only if the swap was successful */ @Inline public static boolean addressTryCompareAndSwap(Object ref, Offset offset, Address old, Address value) { if (NEEDS_ADDRESS_GC_WRITE_BARRIER || NEEDS_ADDRESS_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().addressTryCompareAndSwap(src, src.toAddress().plus(offset), old, value, offset.toWord(), Word.zero(), // do not have location metadata INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return false; } /** {@code true} if the garbage collector requires write barriers on Extent putfield, arraystore or modifycheck */ private static final boolean NEEDS_EXTENT_GC_WRITE_BARRIER = Selected.Constraints.get().needsExtentWriteBarrier(); /** {@code true} if the VM requires write barriers on Extent putfield */ public static final boolean NEEDS_EXTENT_PUTFIELD_BARRIER = NEEDS_EXTENT_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on Extent getfield or arrayload */ private static final boolean NEEDS_EXTENT_GC_READ_BARRIER = Selected.Constraints.get().needsExtentReadBarrier(); /** {@code true} if the VM requires read barriers on Extent getfield */ public static final boolean NEEDS_EXTENT_GETFIELD_BARRIER = NEEDS_EXTENT_GC_READ_BARRIER; /** * Barrier for writes of Extents into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void extentFieldWrite(Object ref, Extent value, Offset offset, int locationMetadata) { if (NEEDS_EXTENT_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().extentWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of Extents from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static Extent extentFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_EXTENT_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().extentRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return Extent.zero(); } /** {@code true} if the garbage collector requires write barriers on Offset putfield, arraystore or modifycheck */ private static final boolean NEEDS_OFFSET_GC_WRITE_BARRIER = Selected.Constraints.get().needsOffsetWriteBarrier(); /** {@code true} if the VM requires write barriers on Offset putfield */ public static final boolean NEEDS_OFFSET_PUTFIELD_BARRIER = NEEDS_OFFSET_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on Offset getfield or arrayload */ private static final boolean NEEDS_OFFSET_GC_READ_BARRIER = Selected.Constraints.get().needsOffsetReadBarrier(); /** {@code true} if the VM requires read barriers on Offset getfield */ public static final boolean NEEDS_OFFSET_GETFIELD_BARRIER = NEEDS_OFFSET_GC_READ_BARRIER; /** * Barrier for writes of Offsets into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void offsetFieldWrite(Object ref, Offset value, Offset offset, int locationMetadata) { if (NEEDS_OFFSET_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().offsetWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of Offsets from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static Offset offsetFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_OFFSET_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().offsetRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return Offset.zero(); } /** {@code true} if the garbage collector requires write barriers on reference putfield, arraystore or modifycheck */ private static final boolean NEEDS_OBJECT_GC_WRITE_BARRIER = Selected.Constraints.get().needsObjectReferenceWriteBarrier(); /** {@code true} if the VM requires write barriers on reference putfield */ public static final boolean NEEDS_OBJECT_PUTFIELD_BARRIER = NEEDS_OBJECT_GC_WRITE_BARRIER; /** {@code true} if the VM requires write barriers on reference arraystore */ public static final boolean NEEDS_OBJECT_ASTORE_BARRIER = NEEDS_OBJECT_GC_WRITE_BARRIER; /** {@code true} if the garbage collector requires read barriers on reference getfield or arrayload */ private static final boolean NEEDS_OBJECT_GC_READ_BARRIER = Selected.Constraints.get().needsObjectReferenceReadBarrier(); /** {@code true} if the VM requires read barriers on reference getfield */ public static final boolean NEEDS_OBJECT_GETFIELD_BARRIER = NEEDS_OBJECT_GC_READ_BARRIER; /** {@code true} if the VM requires read barriers on reference arrayload */ public static final boolean NEEDS_OBJECT_ALOAD_BARRIER = NEEDS_OBJECT_GC_READ_BARRIER; /** {@code true} if the garbage collector supports the bulk copy operation */ public static final boolean OBJECT_BULK_COPY_SUPPORTED = !(NEEDS_OBJECT_ASTORE_BARRIER || NEEDS_OBJECT_ALOAD_BARRIER) || Selected.Constraints.get().objectReferenceBulkCopySupported(); /** * Barrier for writes of objects into fields of instances (i.e. putfield). * * @param ref the object which is the subject of the putfield * @param value the new value for the field * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void objectFieldWrite(Object ref, Object value, Offset offset, int locationMetadata) { if (NEEDS_OBJECT_GC_WRITE_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); Selected.Mutator.get().objectReferenceWrite(src, src.toAddress().plus(offset), ObjectReference.fromObject(value), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for writes of objects into arrays (i.e. aastore). * * @param ref the array which is the subject of the astore * @param index the index into the array where the new reference * resides. The index is the "natural" index into the array, for * example a[index]. * @param value the value to be stored. */ @Inline @Entrypoint public static void objectArrayWrite(Object[] ref, int index, Object value) { if (NEEDS_OBJECT_GC_WRITE_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS); Selected.Mutator.get().objectReferenceWrite(array, array.toAddress().plus(offset), ObjectReference.fromObject(value), offset.toWord(), Word.zero(), ARRAY_ELEMENT); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of objects from fields of instances (i.e. getfield). * * @param ref the object which is the subject of the getfield * @param offset the offset of the field to be read * @param locationMetadata an int that encodes the source location being read * @return The value read from the field. */ @Inline @Entrypoint public static Object objectFieldRead(Object ref, Offset offset, int locationMetadata) { if (NEEDS_OBJECT_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().objectReferenceRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD).toObject(); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return null; } /** * Barrier for loads of objects from fields of arrays (i.e. aaload). * * @param ref the array containing the reference. * @param index the index into the array were the reference resides. * @return the value read from the array */ @Inline @Entrypoint public static Object objectArrayRead(Object[] ref, int index) { if (NEEDS_OBJECT_GC_READ_BARRIER) { ObjectReference array = ObjectReference.fromObject(ref); Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS); return Selected.Mutator.get().objectReferenceRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT).toObject(); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return null; } /** * Barrier for a bulk copy of objects (i.e. in an array copy). * * @param src The source array * @param srcOffset The starting source offset * @param dst The destination array * @param dstOffset The starting destination offset * @param bytes The number of bytes to be copied */ @Inline public static void objectBulkCopy(Object[] src, Offset srcOffset, Object[] dst, Offset dstOffset, int bytes) { if (VM.VerifyAssertions) VM._assert(OBJECT_BULK_COPY_SUPPORTED); if (!Selected.Mutator.get().objectReferenceBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) { Memory.alignedWordCopy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes); } } /** {@code true} if the selected plan requires write barriers on reference putstatic */ private static final boolean NEEDS_OBJECT_GC_PUTSTATIC_BARRIER = Selected.Constraints.get().needsObjectReferenceNonHeapWriteBarrier(); /** {@code true} if the selected plan requires write barriers on reference putstatic */ public static final boolean NEEDS_OBJECT_PUTSTATIC_BARRIER = NEEDS_OBJECT_GC_PUTSTATIC_BARRIER; /** {@code true} if the selected plan requires read barriers on reference getstatic */ private static final boolean NEEDS_OBJECT_GC_GETSTATIC_BARRIER = Selected.Constraints.get().needsObjectReferenceNonHeapReadBarrier(); /** {@code true} if the selected plan requires read barriers on reference getstatic */ public static final boolean NEEDS_OBJECT_GETSTATIC_BARRIER = NEEDS_OBJECT_GC_GETSTATIC_BARRIER; /** * Barrier for writes of objects from statics (eg putstatic) * * @param value the new value to be stored * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being modified */ @Inline @Entrypoint public static void objectStaticWrite(Object value, Offset offset, int locationMetadata) { if (NEEDS_OBJECT_GC_PUTSTATIC_BARRIER) { ObjectReference src = ObjectReference.fromObject(Magic.getJTOC()); Selected.Mutator.get().objectReferenceNonHeapWrite(src.toAddress().plus(offset), ObjectReference.fromObject(value), offset.toWord(), Word.fromIntZeroExtend(locationMetadata)); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); } /** * Barrier for loads of objects from statics (i.e. getstatic) * * @param offset the offset of the field to be modified * @param locationMetadata an int that encodes the source location being read * @return the value read from the field */ @Inline @Entrypoint public static Object objectStaticRead(Offset offset, int locationMetadata) { if (NEEDS_OBJECT_GC_GETSTATIC_BARRIER) { ObjectReference src = ObjectReference.fromObject(Magic.getJTOC()); return Selected.Mutator.get().objectReferenceNonHeapRead( src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata)).toObject(); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return null; } /** * Barrier for conditional compare and exchange of reference fields. * * @param ref the object which is the subject of the compare and exchanges * @param offset the offset of the field to be modified * @param old the old value to swap out * @param value the new value for the field * @return {@code true} if and only if the swap was successful */ @Inline public static boolean objectTryCompareAndSwap(Object ref, Offset offset, Object old, Object value) { if (NEEDS_OBJECT_GC_WRITE_BARRIER || NEEDS_OBJECT_GC_READ_BARRIER) { ObjectReference src = ObjectReference.fromObject(ref); return Selected.Mutator.get().objectReferenceTryCompareAndSwap(src, src.toAddress().plus(offset), ObjectReference.fromObject(old), ObjectReference.fromObject(value), offset.toWord(), Word.zero(), // do not have location metadata INSTANCE_FIELD); } else if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return false; } }