001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.mm.mminterface;
014
015import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_BOOLEAN;
016import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_DOUBLE;
017import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_FLOAT;
018import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_LONG;
019import static org.mmtk.utility.Constants.ARRAY_ELEMENT;
020import static org.mmtk.utility.Constants.INSTANCE_FIELD;
021import static org.mmtk.utility.Constants.LOG_BYTES_IN_ADDRESS;
022import static org.mmtk.utility.Constants.LOG_BYTES_IN_CHAR;
023import static org.mmtk.utility.Constants.LOG_BYTES_IN_INT;
024import static org.mmtk.utility.Constants.LOG_BYTES_IN_SHORT;
025
026import org.jikesrvm.VM;
027import org.jikesrvm.runtime.Magic;
028import org.jikesrvm.runtime.Memory;
029import org.vmmagic.pragma.Entrypoint;
030import org.vmmagic.pragma.Inline;
031import org.vmmagic.pragma.Uninterruptible;
032import org.vmmagic.unboxed.Address;
033import org.vmmagic.unboxed.Extent;
034import org.vmmagic.unboxed.ObjectReference;
035import org.vmmagic.unboxed.Offset;
036import org.vmmagic.unboxed.Word;
037
038@Uninterruptible
039public class Barriers {
040  /** {@code true} if the selected plan requires a read barrier on java.lang.ref.Reference types */
041  private static final boolean NEEDS_JAVA_LANG_REFERENCE_GC_READ_BARRIER = Selected.Constraints.get().needsJavaLangReferenceReadBarrier();
042  /** {@code true} if the selected plan requires a read barrier on java.lang.ref.Reference types */
043  public static final boolean NEEDS_JAVA_LANG_REFERENCE_READ_BARRIER = NEEDS_JAVA_LANG_REFERENCE_GC_READ_BARRIER;
044
045  /**
046   * A java.lang.ref.Reference is being read.
047   *
048   * @param obj The non-null referent about to be released to the mutator.
049   * @return The object to release to the mutator.
050   */
051  public static Object javaLangReferenceReadBarrier(Object obj) {
052    if (NEEDS_JAVA_LANG_REFERENCE_GC_READ_BARRIER) {
053      ObjectReference result = Selected.Mutator.get().javaLangReferenceReadBarrier(ObjectReference.fromObject(obj));
054      return result.toObject();
055    } else if (VM.VerifyAssertions)
056      VM._assert(VM.NOT_REACHED);
057    return null;
058  }
059
060  /* bool byte char short int long float double */
061
062  /** {@code true} if the garbage collector requires write barriers on boolean putfield, arraystore or modifycheck */
063  private static final boolean NEEDS_BOOLEAN_GC_WRITE_BARRIER     = Selected.Constraints.get().needsBooleanWriteBarrier();
064  /** {@code true} if the VM requires write barriers on boolean putfield */
065  public static final boolean  NEEDS_BOOLEAN_PUTFIELD_BARRIER     = NEEDS_BOOLEAN_GC_WRITE_BARRIER;
066  /** {@code true} if the VM requires write barriers on boolean arraystore */
067  public static final boolean  NEEDS_BOOLEAN_ASTORE_BARRIER       = NEEDS_BOOLEAN_GC_WRITE_BARRIER;
068  /** {@code true} if the garbage collector requires read barriers on boolean getfield or arrayload */
069  private static final boolean NEEDS_BOOLEAN_GC_READ_BARRIER      = Selected.Constraints.get().needsBooleanReadBarrier();
070  /** {@code true} if the VM requires read barriers on boolean getfield */
071  public static final boolean  NEEDS_BOOLEAN_GETFIELD_BARRIER     = NEEDS_BOOLEAN_GC_READ_BARRIER;
072  /** {@code true} if the VM requires read barriers on boolean arrayload */
073  public static final boolean  NEEDS_BOOLEAN_ALOAD_BARRIER        = NEEDS_BOOLEAN_GC_READ_BARRIER;
074  /** {@code true} if the garbage collector does not support the bulk copy operation */
075  public static final boolean BOOLEAN_BULK_COPY_SUPPORTED         = !(NEEDS_BOOLEAN_ASTORE_BARRIER || NEEDS_BOOLEAN_ALOAD_BARRIER) || Selected.Constraints.get().booleanBulkCopySupported();
076
077  /**
078   * Barrier for writes of booleans into fields of instances (i.e. putfield).
079   *
080   * @param ref the object which is the subject of the putfield
081   * @param value the new value for the field
082   * @param offset the offset of the field to be modified
083   * @param locationMetadata an int that encodes the source location being modified
084   */
085  @Inline
086  @Entrypoint
087  public static void booleanFieldWrite(Object ref, boolean value, Offset offset, int locationMetadata) {
088    if (NEEDS_BOOLEAN_GC_WRITE_BARRIER) {
089      ObjectReference src = ObjectReference.fromObject(ref);
090      Selected.Mutator.get().booleanWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
091    } else if (VM.VerifyAssertions)
092      VM._assert(VM.NOT_REACHED);
093  }
094
095  /**
096   * Barrier for writes of booleans into arrays (i.e. bastore).
097   *
098   * @param ref the array which is the subject of the astore
099   * @param index the index into the array where the new reference
100   * resides.  The index is the "natural" index into the array, for
101   * example a[index].
102   * @param value the value to be stored.
103   */
104  @Inline
105  @Entrypoint
106  public static void booleanArrayWrite(boolean[] ref, int index, boolean value) {
107    if (NEEDS_BOOLEAN_GC_WRITE_BARRIER) {
108      ObjectReference array = ObjectReference.fromObject(ref);
109      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_BOOLEAN);
110      Selected.Mutator.get().booleanWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
111    } else if (VM.VerifyAssertions)
112      VM._assert(VM.NOT_REACHED);
113  }
114
115  /**
116   * Barrier for loads of booleans from fields of instances (i.e. getfield).
117   *
118   * @param ref the object which is the subject of the getfield
119   * @param offset the offset of the field to be read
120   * @param locationMetadata an int that encodes the source location being read
121   * @return The value read from the field.
122   */
123  @Inline
124  @Entrypoint
125  public static boolean booleanFieldRead(Object ref, Offset offset, int locationMetadata) {
126    if (NEEDS_BOOLEAN_GC_READ_BARRIER) {
127      ObjectReference src = ObjectReference.fromObject(ref);
128      return Selected.Mutator.get().booleanRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
129    } else if (VM.VerifyAssertions)
130      VM._assert(VM.NOT_REACHED);
131    return false;
132  }
133
134  /**
135   * Barrier for loads of booleans from fields of arrays (i.e. aload).
136   *
137   * @param ref the array containing the reference.
138   * @param index the index into the array were the reference resides.
139   * @return the value read from the array
140   */
141  @Inline
142  @Entrypoint
143  public static boolean booleanArrayRead(boolean[] ref, int index) {
144    if (NEEDS_BOOLEAN_GC_READ_BARRIER) {
145      ObjectReference array = ObjectReference.fromObject(ref);
146      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_BOOLEAN);
147      return Selected.Mutator.get().booleanRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
148    } else if (VM.VerifyAssertions)
149      VM._assert(VM.NOT_REACHED);
150    return false;
151  }
152
153  /**
154   * Barrier for a bulk copy of booleans (i.e. in an array copy).
155   *
156   * @param src The source array
157   * @param srcOffset The starting source offset
158   * @param dst The destination array
159   * @param dstOffset The starting destination offset
160   * @param bytes The number of bytes to be copied
161   */
162  @Inline
163  public static void booleanBulkCopy(boolean[] src, Offset srcOffset, boolean[] dst, Offset dstOffset, int bytes) {
164    if (VM.VerifyAssertions) VM._assert(BOOLEAN_BULK_COPY_SUPPORTED);
165
166    if (!Selected.Mutator.get().booleanBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
167      Memory.aligned8Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
168    }
169  }
170
171  /** {@code true} if the garbage collector requires write barriers on byte putfield, arraystore or modifycheck */
172  private static final boolean NEEDS_BYTE_GC_WRITE_BARRIER     = Selected.Constraints.get().needsByteWriteBarrier();
173  /** {@code true} if the VM requires write barriers on byte putfield */
174  public static final boolean  NEEDS_BYTE_PUTFIELD_BARRIER     = NEEDS_BYTE_GC_WRITE_BARRIER;
175  /** {@code true} if the VM requires write barriers on byte arraystore */
176  public static final boolean  NEEDS_BYTE_ASTORE_BARRIER       = NEEDS_BYTE_GC_WRITE_BARRIER;
177  /** {@code true} if the garbage collector requires read barriers on byte getfield or arrayload */
178  private static final boolean NEEDS_BYTE_GC_READ_BARRIER      = Selected.Constraints.get().needsByteReadBarrier();
179  /** {@code true} if the VM requires read barriers on byte getfield */
180  public static final boolean  NEEDS_BYTE_GETFIELD_BARRIER     = NEEDS_BYTE_GC_READ_BARRIER;
181  /** {@code true} if the VM requires read barriers on byte arrayload */
182  public static final boolean  NEEDS_BYTE_ALOAD_BARRIER        = NEEDS_BYTE_GC_READ_BARRIER;
183  /** {@code true} if the garbage collector does not support the bulk copy operation */
184  public static final boolean BYTE_BULK_COPY_SUPPORTED         = !(NEEDS_BYTE_ASTORE_BARRIER || NEEDS_BYTE_ALOAD_BARRIER) || Selected.Constraints.get().byteBulkCopySupported();
185
186  /**
187   * Barrier for writes of bytes into fields of instances (i.e. putfield).
188   *
189   * @param ref the object which is the subject of the putfield
190   * @param value the new value for the field
191   * @param offset the offset of the field to be modified
192   * @param locationMetadata an int that encodes the source location being modified
193   */
194  @Inline
195  @Entrypoint
196  public static void byteFieldWrite(Object ref, byte value, Offset offset, int locationMetadata) {
197    if (NEEDS_BYTE_GC_WRITE_BARRIER) {
198      ObjectReference src = ObjectReference.fromObject(ref);
199      Selected.Mutator.get().byteWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
200    } else if (VM.VerifyAssertions)
201      VM._assert(VM.NOT_REACHED);
202  }
203
204  /**
205   * Barrier for writes of bytes into arrays (i.e. bastore).
206   *
207   * @param ref the array which is the subject of the astore
208   * @param index the index into the array where the new reference
209   * resides.  The index is the "natural" index into the array, for
210   * example a[index].
211   * @param value the value to be stored.
212   */
213  @Inline
214  @Entrypoint
215  public static void byteArrayWrite(byte[] ref, int index, byte value) {
216    if (NEEDS_BYTE_GC_WRITE_BARRIER) {
217      ObjectReference array = ObjectReference.fromObject(ref);
218      Offset offset = Offset.fromIntZeroExtend(index);
219      Selected.Mutator.get().byteWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
220    } else if (VM.VerifyAssertions)
221      VM._assert(VM.NOT_REACHED);
222  }
223
224  /**
225   * Barrier for loads of bytes from fields of instances (i.e. getfield).
226   *
227   * @param ref the object which is the subject of the getfield
228   * @param offset the offset of the field to be read
229   * @param locationMetadata an int that encodes the source location being read
230   * @return The value read from the field.
231   */
232  @Inline
233  @Entrypoint
234  public static byte byteFieldRead(Object ref, Offset offset, int locationMetadata) {
235    if (NEEDS_BYTE_GC_READ_BARRIER) {
236      ObjectReference src = ObjectReference.fromObject(ref);
237      return Selected.Mutator.get().byteRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
238    } else if (VM.VerifyAssertions)
239      VM._assert(VM.NOT_REACHED);
240    return 0;
241  }
242
243  /**
244   * Barrier for loads of bytes from fields of arrays (i.e. baload).
245   *
246   * @param ref the array containing the reference.
247   * @param index the index into the array were the reference resides.
248   * @return the value read from the array
249   */
250  @Inline
251  @Entrypoint
252  public static byte byteArrayRead(byte[] ref, int index) {
253    if (NEEDS_BYTE_GC_READ_BARRIER) {
254      ObjectReference array = ObjectReference.fromObject(ref);
255      Offset offset = Offset.fromIntZeroExtend(index);
256      return Selected.Mutator.get().byteRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
257    } else if (VM.VerifyAssertions)
258      VM._assert(VM.NOT_REACHED);
259    return 0;
260  }
261
262  /**
263   * Barrier for a bulk copy of bytes (i.e. in an array copy).
264   *
265   * @param src The source array
266   * @param srcOffset The starting source offset
267   * @param dst The destination array
268   * @param dstOffset The starting destination offset
269   * @param bytes The number of bytes to be copied
270   */
271  @Inline
272  public static void byteBulkCopy(byte[] src, Offset srcOffset, byte[] dst, Offset dstOffset, int bytes) {
273    if (VM.VerifyAssertions) VM._assert(BYTE_BULK_COPY_SUPPORTED);
274
275    if (!Selected.Mutator.get().byteBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
276      Memory.aligned8Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
277    }
278  }
279
280
281  /** {@code true} if the garbage collector requires write barriers on char putfield, arraystore or modifycheck */
282  private static final boolean NEEDS_CHAR_GC_WRITE_BARRIER     = Selected.Constraints.get().needsCharWriteBarrier();
283  /** {@code true} if the VM requires write barriers on char putfield */
284  public static final boolean  NEEDS_CHAR_PUTFIELD_BARRIER     = NEEDS_CHAR_GC_WRITE_BARRIER;
285  /** {@code true} if the VM requires write barriers on char arraystore */
286  public static final boolean  NEEDS_CHAR_ASTORE_BARRIER       = NEEDS_CHAR_GC_WRITE_BARRIER;
287  /** {@code true} if the garbage collector requires read barriers on char getfield or arrayload */
288  private static final boolean NEEDS_CHAR_GC_READ_BARRIER      = Selected.Constraints.get().needsCharReadBarrier();
289  /** {@code true} if the VM requires read barriers on char getfield */
290  public static final boolean  NEEDS_CHAR_GETFIELD_BARRIER     = NEEDS_CHAR_GC_READ_BARRIER;
291  /** {@code true} if the VM requires read barriers on char arrayload */
292  public static final boolean  NEEDS_CHAR_ALOAD_BARRIER        = NEEDS_CHAR_GC_READ_BARRIER;
293  /** {@code true} if the garbage collector does not support the bulk copy operation */
294  public static final boolean CHAR_BULK_COPY_SUPPORTED         = !(NEEDS_CHAR_ASTORE_BARRIER || NEEDS_CHAR_ALOAD_BARRIER) || Selected.Constraints.get().charBulkCopySupported();
295
296  /**
297   * Barrier for writes of chars into fields of instances (i.e. putfield).
298   *
299   * @param ref the object which is the subject of the putfield
300   * @param value the new value for the field
301   * @param offset the offset of the field to be modified
302   * @param locationMetadata an int that encodes the source location being modified
303   */
304  @Inline
305  @Entrypoint
306  public static void charFieldWrite(Object ref, char value, Offset offset, int locationMetadata) {
307    if (NEEDS_CHAR_GC_WRITE_BARRIER) {
308      ObjectReference src = ObjectReference.fromObject(ref);
309      Selected.Mutator.get().charWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
310    } else if (VM.VerifyAssertions)
311      VM._assert(VM.NOT_REACHED);
312  }
313
314  /**
315   * Barrier for writes of chars into arrays (i.e. castore).
316   *
317   * @param ref the array which is the subject of the astore
318   * @param index the index into the array where the new reference
319   * resides.  The index is the "natural" index into the array, for
320   * example a[index].
321   * @param value the value to be stored.
322   */
323  @Inline
324  @Entrypoint
325  public static void charArrayWrite(char[] ref, int index, char value) {
326    if (NEEDS_CHAR_GC_WRITE_BARRIER) {
327      ObjectReference array = ObjectReference.fromObject(ref);
328      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR);
329      Selected.Mutator.get().charWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
330    } else if (VM.VerifyAssertions)
331      VM._assert(VM.NOT_REACHED);
332  }
333
334  /**
335   * Barrier for loads of chars from fields of instances (i.e. getfield).
336   *
337   * @param ref the object which is the subject of the getfield
338   * @param offset the offset of the field to be read
339   * @param locationMetadata an int that encodes the source location being read
340   * @return The value read from the field.
341   */
342  @Inline
343  @Entrypoint
344  public static char charFieldRead(Object ref, Offset offset, int locationMetadata) {
345    if (NEEDS_CHAR_GC_READ_BARRIER) {
346      ObjectReference src = ObjectReference.fromObject(ref);
347      return Selected.Mutator.get().charRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
348    } else if (VM.VerifyAssertions)
349      VM._assert(VM.NOT_REACHED);
350    return 0;
351  }
352
353  /**
354   * Barrier for loads of chars from fields of arrays (i.e. caload).
355   *
356   * @param ref the array containing the reference.
357   * @param index the index into the array were the reference resides.
358   * @return the value read from the array
359   */
360  @Inline
361  @Entrypoint
362  public static char charArrayRead(char[] ref, int index) {
363    if (NEEDS_CHAR_GC_READ_BARRIER) {
364      ObjectReference array = ObjectReference.fromObject(ref);
365      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR);
366      return Selected.Mutator.get().charRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
367    } else if (VM.VerifyAssertions)
368      VM._assert(VM.NOT_REACHED);
369    return 0;
370  }
371
372  /**
373   * Barrier for a bulk copy of chars (i.e. in an array copy).
374   *
375   * @param src The source array
376   * @param srcOffset The starting source offset
377   * @param dst The destination array
378   * @param dstOffset The starting destination offset
379   * @param bytes The number of bytes to be copied
380   */
381  @Inline
382  public static void charBulkCopy(char[] src, Offset srcOffset, char[] dst, Offset dstOffset, int bytes) {
383    if (VM.VerifyAssertions) VM._assert(CHAR_BULK_COPY_SUPPORTED);
384
385    if (!Selected.Mutator.get().charBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
386      Memory.aligned16Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
387    }
388  }
389
390
391  /** {@code true} if the garbage collector requires write barriers on short putfield, arraystore or modifycheck */
392  private static final boolean NEEDS_SHORT_GC_WRITE_BARRIER     = Selected.Constraints.get().needsShortWriteBarrier();
393  /** {@code true} if the VM requires write barriers on short putfield */
394  public static final boolean  NEEDS_SHORT_PUTFIELD_BARRIER     = NEEDS_SHORT_GC_WRITE_BARRIER;
395  /** {@code true} if the VM requires write barriers on short arraystore */
396  public static final boolean  NEEDS_SHORT_ASTORE_BARRIER       = NEEDS_SHORT_GC_WRITE_BARRIER;
397  /** {@code true} if the garbage collector requires read barriers on short getfield or arrayload */
398  private static final boolean NEEDS_SHORT_GC_READ_BARRIER      = Selected.Constraints.get().needsShortReadBarrier();
399  /** {@code true} if the VM requires read barriers on short getfield */
400  public static final boolean  NEEDS_SHORT_GETFIELD_BARRIER     = NEEDS_SHORT_GC_READ_BARRIER;
401  /** {@code true} if the VM requires read barriers on short arrayload */
402  public static final boolean  NEEDS_SHORT_ALOAD_BARRIER        = NEEDS_SHORT_GC_READ_BARRIER;
403  /** {@code true} if the garbage collector does not support the bulk copy operation */
404  public static final boolean SHORT_BULK_COPY_SUPPORTED         = !(NEEDS_SHORT_ASTORE_BARRIER || NEEDS_SHORT_ALOAD_BARRIER) || Selected.Constraints.get().shortBulkCopySupported();
405
406  /**
407   * Barrier for writes of shorts into fields of instances (i.e. putfield).
408   *
409   * @param ref the object which is the subject of the putfield
410   * @param value the new value for the field
411   * @param offset the offset of the field to be modified
412   * @param locationMetadata an int that encodes the source location being modified
413   */
414  @Inline
415  @Entrypoint
416  public static void shortFieldWrite(Object ref, short value, Offset offset, int locationMetadata) {
417    if (NEEDS_SHORT_GC_WRITE_BARRIER) {
418      ObjectReference src = ObjectReference.fromObject(ref);
419      Selected.Mutator.get().shortWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
420    } else if (VM.VerifyAssertions)
421      VM._assert(VM.NOT_REACHED);
422  }
423
424  /**
425   * Barrier for writes of shorts into arrays (i.e. sastore).
426   *
427   * @param ref the array which is the subject of the astore
428   * @param index the index into the array where the new reference
429   * resides.  The index is the "natural" index into the array, for
430   * example a[index].
431   * @param value the value to be stored.
432   */
433  @Inline
434  @Entrypoint
435  public static void shortArrayWrite(short[] ref, int index, short value) {
436    if (NEEDS_SHORT_GC_WRITE_BARRIER) {
437      ObjectReference array = ObjectReference.fromObject(ref);
438      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_SHORT);
439      Selected.Mutator.get().shortWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
440    } else if (VM.VerifyAssertions)
441      VM._assert(VM.NOT_REACHED);
442  }
443
444  /**
445   * Barrier for loads of shorts from fields of instances (i.e. getfield).
446   *
447   * @param ref the object which is the subject of the getfield
448   * @param offset the offset of the field to be read
449   * @param locationMetadata an int that encodes the source location being read
450   * @return The value read from the field.
451   */
452  @Inline
453  @Entrypoint
454  public static short shortFieldRead(Object ref, Offset offset, int locationMetadata) {
455    if (NEEDS_SHORT_GC_READ_BARRIER) {
456      ObjectReference src = ObjectReference.fromObject(ref);
457      return Selected.Mutator.get().shortRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
458    } else if (VM.VerifyAssertions)
459      VM._assert(VM.NOT_REACHED);
460    return 0;
461  }
462
463  /**
464   * Barrier for loads of shorts from fields of arrays (i.e. saload).
465   *
466   * @param ref the array containing the reference.
467   * @param index the index into the array were the reference resides.
468   * @return the value read from the array
469   */
470  @Inline
471  @Entrypoint
472  public static short shortArrayRead(short[] ref, int index) {
473    if (NEEDS_SHORT_GC_READ_BARRIER) {
474      ObjectReference array = ObjectReference.fromObject(ref);
475      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_SHORT);
476      return Selected.Mutator.get().shortRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
477    } else if (VM.VerifyAssertions)
478      VM._assert(VM.NOT_REACHED);
479    return 0;
480  }
481
482  /**
483   * Barrier for a bulk copy of shorts (i.e. in an array copy).
484   *
485   * @param src The source array
486   * @param srcOffset The starting source offset
487   * @param dst The destination array
488   * @param dstOffset The starting destination offset
489   * @param bytes The number of bytes to be copied
490   */
491  @Inline
492  public static void shortBulkCopy(short[] src, Offset srcOffset, short[] dst, Offset dstOffset, int bytes) {
493    if (VM.VerifyAssertions) VM._assert(SHORT_BULK_COPY_SUPPORTED);
494
495    if (!Selected.Mutator.get().shortBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
496      Memory.aligned16Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
497    }
498  }
499
500
501
502  /** {@code true} if the garbage collector requires write barriers on int putfield, arraystore or modifycheck */
503  private static final boolean NEEDS_INT_GC_WRITE_BARRIER     = Selected.Constraints.get().needsIntWriteBarrier();
504  /** {@code true} if the VM requires write barriers on int putfield */
505  public static final boolean  NEEDS_INT_PUTFIELD_BARRIER     = NEEDS_INT_GC_WRITE_BARRIER;
506  /** {@code true} if the VM requires write barriers on int arraystore */
507  public static final boolean  NEEDS_INT_ASTORE_BARRIER       = NEEDS_INT_GC_WRITE_BARRIER;
508  /** {@code true} if the garbage collector requires read barriers on int getfield or arrayload */
509  private static final boolean NEEDS_INT_GC_READ_BARRIER      = Selected.Constraints.get().needsIntReadBarrier();
510  /** {@code true} if the VM requires read barriers on int getfield */
511  public static final boolean  NEEDS_INT_GETFIELD_BARRIER     = NEEDS_INT_GC_READ_BARRIER;
512  /** {@code true} if the VM requires read barriers on int arrayload */
513  public static final boolean  NEEDS_INT_ALOAD_BARRIER        = NEEDS_INT_GC_READ_BARRIER;
514  /** {@code true} if the garbage collector does not support the bulk copy operation */
515  public static final boolean INT_BULK_COPY_SUPPORTED         = !(NEEDS_INT_ASTORE_BARRIER || NEEDS_INT_ALOAD_BARRIER) || Selected.Constraints.get().intBulkCopySupported();
516
517  /**
518   * Barrier for writes of ints into fields of instances (i.e. putfield).
519   *
520   * @param ref the object which is the subject of the putfield
521   * @param value the new value for the field
522   * @param offset the offset of the field to be modified
523   * @param locationMetadata an int that encodes the source location being modified
524   */
525  @Inline
526  @Entrypoint
527  public static void intFieldWrite(Object ref, int value, Offset offset, int locationMetadata) {
528    if (NEEDS_INT_GC_WRITE_BARRIER) {
529      ObjectReference src = ObjectReference.fromObject(ref);
530      Selected.Mutator.get().intWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
531    } else if (VM.VerifyAssertions)
532      VM._assert(VM.NOT_REACHED);
533  }
534
535  /**
536   * Barrier for writes of ints into arrays (i.e. iastore).
537   *
538   * @param ref the array which is the subject of the astore
539   * @param index the index into the array where the new reference
540   * resides.  The index is the "natural" index into the array, for
541   * example a[index].
542   * @param value the value to be stored.
543   */
544  @Inline
545  @Entrypoint
546  public static void intArrayWrite(int[] ref, int index, int value) {
547    if (NEEDS_INT_GC_WRITE_BARRIER) {
548      ObjectReference array = ObjectReference.fromObject(ref);
549      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_INT);
550      Selected.Mutator.get().intWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
551    } else if (VM.VerifyAssertions)
552      VM._assert(VM.NOT_REACHED);
553  }
554
555  /**
556   * Barrier for loads of ints from fields of instances (i.e. getfield).
557   *
558   * @param ref the object which is the subject of the getfield
559   * @param offset the offset of the field to be read
560   * @param locationMetadata an int that encodes the source location being read
561   * @return The value read from the field.
562   */
563  @Inline
564  @Entrypoint
565  public static int intFieldRead(Object ref, Offset offset, int locationMetadata) {
566    if (NEEDS_INT_GC_READ_BARRIER) {
567      ObjectReference src = ObjectReference.fromObject(ref);
568      return Selected.Mutator.get().intRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
569    } else if (VM.VerifyAssertions)
570      VM._assert(VM.NOT_REACHED);
571    return 0;
572  }
573
574  /**
575   * Barrier for loads of ints from fields of arrays (i.e. iaload).
576   *
577   * @param ref the array containing the reference.
578   * @param index the index into the array were the reference resides.
579   * @return the value read from the array
580   */
581  @Inline
582  @Entrypoint
583  public static int intArrayRead(int[] ref, int index) {
584    if (NEEDS_INT_GC_READ_BARRIER) {
585      ObjectReference array = ObjectReference.fromObject(ref);
586      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_INT);
587      return Selected.Mutator.get().intRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
588    } else if (VM.VerifyAssertions)
589      VM._assert(VM.NOT_REACHED);
590    return 0;
591  }
592
593  /**
594   * Barrier for a bulk copy of ints (i.e. in an array copy).
595   *
596   * @param src The source array
597   * @param srcOffset The starting source offset
598   * @param dst The destination array
599   * @param dstOffset The starting destination offset
600   * @param bytes The number of bytes to be copied
601   */
602  @Inline
603  public static void intBulkCopy(int[] src, Offset srcOffset, int[] dst, Offset dstOffset, int bytes) {
604    if (VM.VerifyAssertions) VM._assert(INT_BULK_COPY_SUPPORTED);
605
606    if (!Selected.Mutator.get().intBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
607      Memory.aligned32Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
608    }
609  }
610
611  /**
612   * Barrier for conditional compare and exchange of int fields.
613   * @param ref the object which is the subject of the compare and exchanges
614   * @param offset the offset of the field to be modified
615   * @param old the old value to swap out
616   * @param value the new value for the field
617   * @return {@code true} if and only if the swap was successful
618   */
619  @Inline
620  public static boolean intTryCompareAndSwap(Object ref, Offset offset, int old, int value) {
621    if (NEEDS_INT_GC_WRITE_BARRIER || NEEDS_INT_GC_READ_BARRIER) {
622      ObjectReference src = ObjectReference.fromObject(ref);
623      return Selected.Mutator.get().intTryCompareAndSwap(src, src.toAddress().plus(offset), old, value, offset.toWord(),
624                                                         Word.zero(), // do not have location metadata
625                                                         INSTANCE_FIELD);
626    } else if (VM.VerifyAssertions)
627      VM._assert(VM.NOT_REACHED);
628    return false;
629  }
630
631
632  /** {@code true} if the garbage collector requires write barriers on long putfield, arraystore or modifycheck */
633  private static final boolean NEEDS_LONG_GC_WRITE_BARRIER     = Selected.Constraints.get().needsLongWriteBarrier();
634  /** {@code true} if the VM requires write barriers on long putfield */
635  public static final boolean  NEEDS_LONG_PUTFIELD_BARRIER     = NEEDS_LONG_GC_WRITE_BARRIER;
636  /** {@code true} if the VM requires write barriers on long arraystore */
637  public static final boolean  NEEDS_LONG_ASTORE_BARRIER       = NEEDS_LONG_GC_WRITE_BARRIER;
638  /** {@code true} if the garbage collector requires read barriers on long getfield or arrayload */
639  private static final boolean NEEDS_LONG_GC_READ_BARRIER      = Selected.Constraints.get().needsLongReadBarrier();
640  /** {@code true} if the VM requires read barriers on long getfield */
641  public static final boolean  NEEDS_LONG_GETFIELD_BARRIER     = NEEDS_LONG_GC_READ_BARRIER;
642  /** {@code true} if the VM requires read barriers on long arrayload */
643  public static final boolean  NEEDS_LONG_ALOAD_BARRIER        = NEEDS_LONG_GC_READ_BARRIER;
644  /** {@code true} if the garbage collector supports the bulk copy operation */
645  public static final boolean LONG_BULK_COPY_SUPPORTED         = !(NEEDS_LONG_ASTORE_BARRIER || NEEDS_LONG_ALOAD_BARRIER) || Selected.Constraints.get().longBulkCopySupported();
646
647  /**
648   * Barrier for writes of longs into fields of instances (i.e. putfield).
649   *
650   * @param ref the object which is the subject of the putfield
651   * @param value the new value for the field
652   * @param offset the offset of the field to be modified
653   * @param locationMetadata an int that encodes the source location being modified
654   */
655  @Inline
656  @Entrypoint
657  public static void longFieldWrite(Object ref, long value, Offset offset, int locationMetadata) {
658    if (NEEDS_LONG_GC_WRITE_BARRIER) {
659      ObjectReference src = ObjectReference.fromObject(ref);
660      Selected.Mutator.get().longWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
661    } else if (VM.VerifyAssertions)
662      VM._assert(VM.NOT_REACHED);
663  }
664
665  /**
666   * Barrier for writes of longs into arrays (i.e. lastore).
667   *
668   * @param ref the array which is the subject of the astore
669   * @param index the index into the array where the new reference
670   * resides.  The index is the "natural" index into the array, for
671   * example a[index].
672   * @param value the value to be stored.
673   */
674  @Inline
675  @Entrypoint
676  public static void longArrayWrite(long[] ref, int index, long value) {
677    if (NEEDS_LONG_GC_WRITE_BARRIER) {
678      ObjectReference array = ObjectReference.fromObject(ref);
679      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_LONG);
680      Selected.Mutator.get().longWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
681    } else if (VM.VerifyAssertions)
682      VM._assert(VM.NOT_REACHED);
683  }
684
685  /**
686   * Barrier for loads of longs from fields of instances (i.e. getfield).
687   *
688   * @param ref the object which is the subject of the getfield
689   * @param offset the offset of the field to be read
690   * @param locationMetadata an int that encodes the source location being read
691   * @return The value read from the field.
692   */
693  @Inline
694  @Entrypoint
695  public static long longFieldRead(Object ref, Offset offset, int locationMetadata) {
696    if (NEEDS_LONG_GC_READ_BARRIER) {
697      ObjectReference src = ObjectReference.fromObject(ref);
698      return Selected.Mutator.get().longRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
699    } else if (VM.VerifyAssertions)
700      VM._assert(VM.NOT_REACHED);
701    return 0;
702  }
703
704  /**
705   * Barrier for loads of longs from fields of arrays (i.e. laload).
706   *
707   * @param ref the array containing the reference.
708   * @param index the index into the array were the reference resides.
709   * @return the value read from the array
710   */
711  @Inline
712  @Entrypoint
713  public static long longArrayRead(long[] ref, int index) {
714    if (NEEDS_LONG_GC_READ_BARRIER) {
715      ObjectReference array = ObjectReference.fromObject(ref);
716      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_LONG);
717      return Selected.Mutator.get().longRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
718    } else if (VM.VerifyAssertions)
719      VM._assert(VM.NOT_REACHED);
720    return 0;
721  }
722
723  /**
724   * Barrier for conditional compare and exchange of long fields.
725   * @param ref the object which is the subject of the compare and exchanges
726   * @param offset the offset of the field to be modified
727   * @param old the old value to swap out
728   * @param value the new value for the field
729   * @return {@code true} if and only if the swap was successful
730   */
731  @Inline
732  public static boolean longTryCompareAndSwap(Object ref, Offset offset, long old, long value) {
733    if (NEEDS_LONG_GC_WRITE_BARRIER || NEEDS_LONG_GC_READ_BARRIER) {
734      ObjectReference src = ObjectReference.fromObject(ref);
735      return Selected.Mutator.get().longTryCompareAndSwap(src, src.toAddress().plus(offset), old, value, offset.toWord(),
736                                                          Word.zero(), // do not have location metadata
737                                                          INSTANCE_FIELD);
738    } else if (VM.VerifyAssertions)
739      VM._assert(VM.NOT_REACHED);
740    return false;
741  }
742
743  /**
744   * Barrier for a bulk copy of longs (i.e. in an array copy).
745   * @param src The source array
746   * @param srcOffset The starting source offset
747   * @param dst The destination array
748   * @param dstOffset The starting destination offset
749   * @param bytes The number of bytes to be copied
750   */
751  @Inline
752  public static void longBulkCopy(long[] src, Offset srcOffset, long[] dst, Offset dstOffset, int bytes) {
753    if (VM.VerifyAssertions) VM._assert(LONG_BULK_COPY_SUPPORTED);
754
755    if (!Selected.Mutator.get().longBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
756      Memory.aligned64Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
757    }
758  }
759
760
761  /** {@code true} if the garbage collector requires write barriers on float putfield, arraystore or modifycheck */
762  private static final boolean NEEDS_FLOAT_GC_WRITE_BARRIER     = Selected.Constraints.get().needsFloatWriteBarrier();
763  /** {@code true} if the VM requires write barriers on float putfield */
764  public static final boolean  NEEDS_FLOAT_PUTFIELD_BARRIER     = NEEDS_FLOAT_GC_WRITE_BARRIER;
765  /** {@code true} if the VM requires write barriers on float arraystore */
766  public static final boolean  NEEDS_FLOAT_ASTORE_BARRIER       = NEEDS_FLOAT_GC_WRITE_BARRIER;
767  /** {@code true} if the garbage collector requires read barriers on float getfield or arrayload */
768  private static final boolean NEEDS_FLOAT_GC_READ_BARRIER      = Selected.Constraints.get().needsFloatReadBarrier();
769  /** {@code true} if the VM requires read barriers on float getfield */
770  public static final boolean  NEEDS_FLOAT_GETFIELD_BARRIER     = NEEDS_FLOAT_GC_READ_BARRIER;
771  /** {@code true} if the VM requires read barriers on float arrayload */
772  public static final boolean  NEEDS_FLOAT_ALOAD_BARRIER        = NEEDS_FLOAT_GC_READ_BARRIER;
773  /** {@code true} if the garbage collector supports the bulk copy operation */
774  public static final boolean FLOAT_BULK_COPY_SUPPORTED         = !(NEEDS_FLOAT_ASTORE_BARRIER || NEEDS_FLOAT_ALOAD_BARRIER) || Selected.Constraints.get().floatBulkCopySupported();
775
776  /**
777   * Barrier for writes of floats into fields of instances (i.e. putfield).
778   *
779   * @param ref the object which is the subject of the putfield
780   * @param value the new value for the field
781   * @param offset the offset of the field to be modified
782   * @param locationMetadata an int that encodes the source location being modified
783   */
784  @Inline
785  @Entrypoint
786  public static void floatFieldWrite(Object ref, float value, Offset offset, int locationMetadata) {
787    if (NEEDS_FLOAT_GC_WRITE_BARRIER) {
788      ObjectReference src = ObjectReference.fromObject(ref);
789      Selected.Mutator.get().floatWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
790    } else if (VM.VerifyAssertions)
791      VM._assert(VM.NOT_REACHED);
792  }
793
794  /**
795   * Barrier for writes of floats into arrays (i.e. fastore).
796   *
797   * @param ref the array which is the subject of the astore
798   * @param index the index into the array where the new reference
799   * resides.  The index is the "natural" index into the array, for
800   * example a[index].
801   * @param value the value to be stored.
802   */
803  @Inline
804  @Entrypoint
805  public static void floatArrayWrite(float[] ref, int index, float value) {
806    if (NEEDS_FLOAT_GC_WRITE_BARRIER) {
807      ObjectReference array = ObjectReference.fromObject(ref);
808      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT);
809      Selected.Mutator.get().floatWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
810    } else if (VM.VerifyAssertions)
811      VM._assert(VM.NOT_REACHED);
812  }
813
814  /**
815   * Barrier for loads of floats from fields of instances (i.e. getfield).
816   *
817   * @param ref the object which is the subject of the getfield
818   * @param offset the offset of the field to be read
819   * @param locationMetadata an int that encodes the source location being read
820   * @return The value read from the field.
821   */
822  @Inline
823  @Entrypoint
824  public static float floatFieldRead(Object ref, Offset offset, int locationMetadata) {
825    if (NEEDS_FLOAT_GC_READ_BARRIER) {
826      ObjectReference src = ObjectReference.fromObject(ref);
827      return Selected.Mutator.get().floatRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
828    } else if (VM.VerifyAssertions)
829      VM._assert(VM.NOT_REACHED);
830    return 0;
831  }
832
833  /**
834   * Barrier for loads of floats from fields of arrays (i.e. faload).
835   *
836   * @param ref the array containing the reference.
837   * @param index the index into the array were the reference resides.
838   * @return the value read from the array
839   */
840  @Inline
841  @Entrypoint
842  public static float floatArrayRead(float[] ref, int index) {
843    if (NEEDS_FLOAT_GC_READ_BARRIER) {
844      ObjectReference array = ObjectReference.fromObject(ref);
845      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT);
846      return Selected.Mutator.get().floatRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
847    } else if (VM.VerifyAssertions)
848      VM._assert(VM.NOT_REACHED);
849    return 0;
850  }
851
852  /**
853   * Barrier for a bulk copy of floats (i.e. in an array copy).
854   *
855   * @param src The source array
856   * @param srcOffset The starting source offset
857   * @param dst The destination array
858   * @param dstOffset The starting destination offset
859   * @param bytes The number of bytes to be copied
860   */
861  @Inline
862  public static void floatBulkCopy(float[] src, Offset srcOffset, float[] dst, Offset dstOffset, int bytes) {
863    if (VM.VerifyAssertions) VM._assert(FLOAT_BULK_COPY_SUPPORTED);
864
865    if (!Selected.Mutator.get().floatBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
866      Memory.aligned32Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
867    }
868  }
869
870
871  /** {@code true} if the garbage collector requires write barriers on double putfield, arraystore or modifycheck */
872  private static final boolean NEEDS_DOUBLE_GC_WRITE_BARRIER     = Selected.Constraints.get().needsDoubleWriteBarrier();
873  /** {@code true} if the VM requires write barriers on double putfield */
874  public static final boolean  NEEDS_DOUBLE_PUTFIELD_BARRIER     = NEEDS_DOUBLE_GC_WRITE_BARRIER;
875  /** {@code true} if the VM requires write barriers on double arraystore */
876  public static final boolean  NEEDS_DOUBLE_ASTORE_BARRIER       = NEEDS_DOUBLE_GC_WRITE_BARRIER;
877  /** {@code true} if the garbage collector requires read barriers on double getfield or arrayload */
878  private static final boolean NEEDS_DOUBLE_GC_READ_BARRIER      = Selected.Constraints.get().needsDoubleReadBarrier();
879  /** {@code true} if the VM requires read barriers on double getfield */
880  public static final boolean  NEEDS_DOUBLE_GETFIELD_BARRIER     = NEEDS_DOUBLE_GC_READ_BARRIER;
881  /** {@code true} if the VM requires read barriers on double arrayload */
882  public static final boolean  NEEDS_DOUBLE_ALOAD_BARRIER        = NEEDS_DOUBLE_GC_READ_BARRIER;
883  /** {@code true} if the garbage collector supports the bulk copy operation */
884  public static final boolean DOUBLE_BULK_COPY_SUPPORTED         = !(NEEDS_DOUBLE_ASTORE_BARRIER || NEEDS_DOUBLE_ALOAD_BARRIER) || Selected.Constraints.get().doubleBulkCopySupported();
885
886  /**
887   * Barrier for writes of doubles into fields of instances (i.e. putfield).
888   *
889   * @param ref the object which is the subject of the putfield
890   * @param value the new value for the field
891   * @param offset the offset of the field to be modified
892   * @param locationMetadata an int that encodes the source location being modified
893   */
894  @Inline
895  @Entrypoint
896  public static void doubleFieldWrite(Object ref, double value, Offset offset, int locationMetadata) {
897    if (NEEDS_DOUBLE_GC_WRITE_BARRIER) {
898      ObjectReference src = ObjectReference.fromObject(ref);
899      Selected.Mutator.get().doubleWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
900    } else if (VM.VerifyAssertions)
901      VM._assert(VM.NOT_REACHED);
902  }
903
904  /**
905   * Barrier for writes of doubles into arrays (i.e. dastore).
906   *
907   * @param ref the array which is the subject of the astore
908   * @param index the index into the array where the new reference
909   * resides.  The index is the "natural" index into the array, for
910   * example a[index].
911   * @param value the value to be stored.
912   */
913  @Inline
914  @Entrypoint
915  public static void doubleArrayWrite(double[] ref, int index, double value) {
916    if (NEEDS_DOUBLE_GC_WRITE_BARRIER) {
917      ObjectReference array = ObjectReference.fromObject(ref);
918      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_DOUBLE);
919      Selected.Mutator.get().doubleWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
920    } else if (VM.VerifyAssertions)
921      VM._assert(VM.NOT_REACHED);
922  }
923
924  /**
925   * Barrier for loads of doubles from fields of instances (i.e. getfield).
926   *
927   * @param ref the object which is the subject of the getfield
928   * @param offset the offset of the field to be read
929   * @param locationMetadata an int that encodes the source location being read
930   * @return The value read from the field.
931   */
932  @Inline
933  @Entrypoint
934  public static double doubleFieldRead(Object ref, Offset offset, int locationMetadata) {
935    if (NEEDS_DOUBLE_GC_READ_BARRIER) {
936      ObjectReference src = ObjectReference.fromObject(ref);
937      return Selected.Mutator.get().doubleRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
938    } else if (VM.VerifyAssertions)
939      VM._assert(VM.NOT_REACHED);
940    return 0;
941  }
942
943  /**
944   * Barrier for loads of doubles from fields of arrays (i.e. daload).
945   *
946   * @param ref the array containing the reference.
947   * @param index the index into the array were the reference resides.
948   * @return the value read from the array
949   */
950  @Inline
951  @Entrypoint
952  public static double doubleArrayRead(double[] ref, int index) {
953    if (NEEDS_DOUBLE_GC_READ_BARRIER) {
954      ObjectReference array = ObjectReference.fromObject(ref);
955      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_DOUBLE);
956      return Selected.Mutator.get().doubleRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
957    } else if (VM.VerifyAssertions)
958      VM._assert(VM.NOT_REACHED);
959    return 0;
960  }
961
962  /**
963   * Barrier for a bulk copy of doubles (i.e. in an array copy).
964   *
965   * @param src The source array
966   * @param srcOffset The starting source offset
967   * @param dst The destination array
968   * @param dstOffset The starting destination offset
969   * @param bytes The number of bytes to be copied
970   */
971  @Inline
972  public static void doubleBulkCopy(double[] src, Offset srcOffset, double[] dst, Offset dstOffset, int bytes) {
973    if (VM.VerifyAssertions) VM._assert(DOUBLE_BULK_COPY_SUPPORTED);
974
975    if (!Selected.Mutator.get().doubleBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
976      Memory.aligned64Copy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
977    }
978  }
979
980  /********************************************************************************
981   * Begin support for org.vmmagic.unboxed types (Word, Address, Extent and Offset)
982   *
983   * These types can be witten or read from Object fields via putfield and getfield
984   * Arrays of these special types should not be created in the normal Java way
985   * (i.e. new Word[]) but should be created using WordArray.create() etc.
986   *
987   * TODO: is there a RVM mechanism that prevents new Word[]?
988   */
989
990  /** {@code true} if the garbage collector requires write barriers on Word putfield, arraystore or modifycheck */
991  private static final boolean NEEDS_WORD_GC_WRITE_BARRIER     = Selected.Constraints.get().needsWordWriteBarrier();
992  /** {@code true} if the VM requires write barriers on Word putfield */
993  public static final boolean  NEEDS_WORD_PUTFIELD_BARRIER     = NEEDS_WORD_GC_WRITE_BARRIER;
994  /** {@code true} if the garbage collector requires read barriers on Word getfield or arrayload */
995  private static final boolean NEEDS_WORD_GC_READ_BARRIER      = Selected.Constraints.get().needsWordReadBarrier();
996  /** {@code true} if the VM requires read barriers on Word getfield */
997  public static final boolean  NEEDS_WORD_GETFIELD_BARRIER     = NEEDS_WORD_GC_READ_BARRIER;
998
999  /**
1000   * Barrier for writes of Words into fields of instances (i.e. putfield).
1001   *
1002   * @param ref the object which is the subject of the putfield
1003   * @param value the new value for the field
1004   * @param offset the offset of the field to be modified
1005   * @param locationMetadata an int that encodes the source location being modified
1006   */
1007  @Inline
1008  @Entrypoint
1009  public static void wordFieldWrite(Object ref, Word value, Offset offset, int locationMetadata) {
1010    if (NEEDS_WORD_GC_WRITE_BARRIER) {
1011      ObjectReference src = ObjectReference.fromObject(ref);
1012      Selected.Mutator.get().wordWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1013    } else if (VM.VerifyAssertions)
1014      VM._assert(VM.NOT_REACHED);
1015  }
1016
1017  /**
1018   * Barrier for loads of Words from fields of instances (i.e. getfield).
1019   *
1020   * @param ref the object which is the subject of the getfield
1021   * @param offset the offset of the field to be read
1022   * @param locationMetadata an int that encodes the source location being read
1023   * @return The value read from the field.
1024   */
1025  @Inline
1026  @Entrypoint
1027  public static Word wordFieldRead(Object ref, Offset offset, int locationMetadata) {
1028    if (NEEDS_WORD_GC_READ_BARRIER) {
1029      ObjectReference src = ObjectReference.fromObject(ref);
1030      return Selected.Mutator.get().wordRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1031    } else if (VM.VerifyAssertions)
1032      VM._assert(VM.NOT_REACHED);
1033    return Word.zero();
1034  }
1035
1036  /**
1037   * Barrier for conditional compare and exchange of Word fields.
1038   *
1039   * @param ref the object which is the subject of the compare and exchanges
1040   * @param offset the offset of the field to be modified
1041   * @param old the old value to swap out
1042   * @param value the new value for the field
1043   * @return {@code true} if and only if the swap was successful
1044   */
1045  @Inline
1046  public static boolean wordTryCompareAndSwap(Object ref, Offset offset, Word old, Word value) {
1047    if (NEEDS_WORD_GC_WRITE_BARRIER || NEEDS_WORD_GC_READ_BARRIER) {
1048      ObjectReference src = ObjectReference.fromObject(ref);
1049      return Selected.Mutator.get().wordTryCompareAndSwap(src, src.toAddress().plus(offset), old, value, offset.toWord(),
1050                                                          Word.zero(), // do not have location metadata
1051                                                          INSTANCE_FIELD);
1052    } else if (VM.VerifyAssertions)
1053      VM._assert(VM.NOT_REACHED);
1054    return false;
1055  }
1056
1057  /** {@code true} if the garbage collector requires write barriers on Address putfield, arraystore or modifycheck */
1058  private static final boolean NEEDS_ADDRESS_GC_WRITE_BARRIER     = Selected.Constraints.get().needsAddressWriteBarrier();
1059  /** {@code true} if the VM requires write barriers on Address putfield */
1060  public static final boolean  NEEDS_ADDRESS_PUTFIELD_BARRIER     = NEEDS_ADDRESS_GC_WRITE_BARRIER;
1061  /** {@code true} if the garbage collector requires read barriers on Address getfield or arrayload */
1062  private static final boolean NEEDS_ADDRESS_GC_READ_BARRIER      = Selected.Constraints.get().needsAddressReadBarrier();
1063  /** {@code true} if the VM requires read barriers on Address getfield */
1064  public static final boolean  NEEDS_ADDRESS_GETFIELD_BARRIER     = NEEDS_ADDRESS_GC_READ_BARRIER;
1065
1066  /**
1067   * Barrier for writes of Address's into fields of instances (i.e. putfield).
1068   *
1069   * @param ref the object which is the subject of the putfield
1070   * @param value the new value for the field
1071   * @param offset the offset of the field to be modified
1072   * @param locationMetadata an int that encodes the source location being modified
1073   */
1074  @Inline
1075  @Entrypoint
1076  public static void addressFieldWrite(Object ref, Address value, Offset offset, int locationMetadata) {
1077    if (NEEDS_ADDRESS_GC_WRITE_BARRIER) {
1078      ObjectReference src = ObjectReference.fromObject(ref);
1079      Selected.Mutator.get().addressWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1080    } else if (VM.VerifyAssertions)
1081      VM._assert(VM.NOT_REACHED);
1082  }
1083
1084  /**
1085   * Barrier for loads of Address's from fields of instances (i.e. getfield).
1086   *
1087   * @param ref the object which is the subject of the getfield
1088   * @param offset the offset of the field to be read
1089   * @param locationMetadata an int that encodes the source location being read
1090   * @return The value read from the field.
1091   */
1092  @Inline
1093  @Entrypoint
1094  public static Address addressFieldRead(Object ref, Offset offset, int locationMetadata) {
1095    if (NEEDS_ADDRESS_GC_READ_BARRIER) {
1096      ObjectReference src = ObjectReference.fromObject(ref);
1097      return Selected.Mutator.get().addressRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1098    } else if (VM.VerifyAssertions)
1099      VM._assert(VM.NOT_REACHED);
1100    return Address.zero();
1101  }
1102
1103  /**
1104   * Barrier for conditional compare and exchange of Address fields.
1105   *
1106   * @param ref the object which is the subject of the compare and exchanges
1107   * @param offset the offset of the field to be modified
1108   * @param old the old value to swap out
1109   * @param value the new value for the field
1110   * @return {@code true} if and only if the swap was successful
1111   */
1112  @Inline
1113  public static boolean addressTryCompareAndSwap(Object ref, Offset offset, Address old, Address value) {
1114    if (NEEDS_ADDRESS_GC_WRITE_BARRIER || NEEDS_ADDRESS_GC_READ_BARRIER) {
1115      ObjectReference src = ObjectReference.fromObject(ref);
1116      return Selected.Mutator.get().addressTryCompareAndSwap(src, src.toAddress().plus(offset), old, value, offset.toWord(),
1117                                                          Word.zero(), // do not have location metadata
1118                                                          INSTANCE_FIELD);
1119    } else if (VM.VerifyAssertions)
1120      VM._assert(VM.NOT_REACHED);
1121    return false;
1122  }
1123
1124  /** {@code true} if the garbage collector requires write barriers on Extent putfield, arraystore or modifycheck */
1125  private static final boolean NEEDS_EXTENT_GC_WRITE_BARRIER     = Selected.Constraints.get().needsExtentWriteBarrier();
1126  /** {@code true} if the VM requires write barriers on Extent putfield */
1127  public static final boolean  NEEDS_EXTENT_PUTFIELD_BARRIER     = NEEDS_EXTENT_GC_WRITE_BARRIER;
1128  /** {@code true} if the garbage collector requires read barriers on Extent getfield or arrayload */
1129  private static final boolean NEEDS_EXTENT_GC_READ_BARRIER      = Selected.Constraints.get().needsExtentReadBarrier();
1130  /** {@code true} if the VM requires read barriers on Extent getfield */
1131  public static final boolean  NEEDS_EXTENT_GETFIELD_BARRIER     = NEEDS_EXTENT_GC_READ_BARRIER;
1132
1133  /**
1134   * Barrier for writes of Extents into fields of instances (i.e. putfield).
1135   *
1136   * @param ref the object which is the subject of the putfield
1137   * @param value the new value for the field
1138   * @param offset the offset of the field to be modified
1139   * @param locationMetadata an int that encodes the source location being modified
1140   */
1141  @Inline
1142  @Entrypoint
1143  public static void extentFieldWrite(Object ref, Extent value, Offset offset, int locationMetadata) {
1144    if (NEEDS_EXTENT_GC_WRITE_BARRIER) {
1145      ObjectReference src = ObjectReference.fromObject(ref);
1146      Selected.Mutator.get().extentWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1147    } else if (VM.VerifyAssertions)
1148      VM._assert(VM.NOT_REACHED);
1149  }
1150
1151  /**
1152   * Barrier for loads of Extents from fields of instances (i.e. getfield).
1153   *
1154   * @param ref the object which is the subject of the getfield
1155   * @param offset the offset of the field to be read
1156   * @param locationMetadata an int that encodes the source location being read
1157   * @return The value read from the field.
1158   */
1159  @Inline
1160  @Entrypoint
1161  public static Extent extentFieldRead(Object ref, Offset offset, int locationMetadata) {
1162    if (NEEDS_EXTENT_GC_READ_BARRIER) {
1163      ObjectReference src = ObjectReference.fromObject(ref);
1164      return Selected.Mutator.get().extentRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1165    } else if (VM.VerifyAssertions)
1166      VM._assert(VM.NOT_REACHED);
1167    return Extent.zero();
1168  }
1169
1170  /** {@code true} if the garbage collector requires write barriers on Offset putfield, arraystore or modifycheck */
1171  private static final boolean NEEDS_OFFSET_GC_WRITE_BARRIER     = Selected.Constraints.get().needsOffsetWriteBarrier();
1172  /** {@code true} if the VM requires write barriers on Offset putfield */
1173  public static final boolean  NEEDS_OFFSET_PUTFIELD_BARRIER     = NEEDS_OFFSET_GC_WRITE_BARRIER;
1174  /** {@code true} if the garbage collector requires read barriers on Offset getfield or arrayload */
1175  private static final boolean NEEDS_OFFSET_GC_READ_BARRIER      = Selected.Constraints.get().needsOffsetReadBarrier();
1176  /** {@code true} if the VM requires read barriers on Offset getfield */
1177  public static final boolean  NEEDS_OFFSET_GETFIELD_BARRIER     = NEEDS_OFFSET_GC_READ_BARRIER;
1178
1179  /**
1180   * Barrier for writes of Offsets into fields of instances (i.e. putfield).
1181   *
1182   * @param ref the object which is the subject of the putfield
1183   * @param value the new value for the field
1184   * @param offset the offset of the field to be modified
1185   * @param locationMetadata an int that encodes the source location being modified
1186   */
1187  @Inline
1188  @Entrypoint
1189  public static void offsetFieldWrite(Object ref, Offset value, Offset offset, int locationMetadata) {
1190    if (NEEDS_OFFSET_GC_WRITE_BARRIER) {
1191      ObjectReference src = ObjectReference.fromObject(ref);
1192      Selected.Mutator.get().offsetWrite(src, src.toAddress().plus(offset), value, offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1193    } else if (VM.VerifyAssertions)
1194      VM._assert(VM.NOT_REACHED);
1195  }
1196
1197  /**
1198   * Barrier for loads of Offsets from fields of instances (i.e. getfield).
1199   *
1200   * @param ref the object which is the subject of the getfield
1201   * @param offset the offset of the field to be read
1202   * @param locationMetadata an int that encodes the source location being read
1203   * @return The value read from the field.
1204   */
1205  @Inline
1206  @Entrypoint
1207  public static Offset offsetFieldRead(Object ref, Offset offset, int locationMetadata) {
1208    if (NEEDS_OFFSET_GC_READ_BARRIER) {
1209      ObjectReference src = ObjectReference.fromObject(ref);
1210      return Selected.Mutator.get().offsetRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1211    } else if (VM.VerifyAssertions)
1212      VM._assert(VM.NOT_REACHED);
1213    return Offset.zero();
1214  }
1215
1216  /** {@code true} if the garbage collector requires write barriers on reference putfield, arraystore or modifycheck */
1217  private static final boolean NEEDS_OBJECT_GC_WRITE_BARRIER     = Selected.Constraints.get().needsObjectReferenceWriteBarrier();
1218  /** {@code true} if the VM requires write barriers on reference putfield */
1219  public static final boolean  NEEDS_OBJECT_PUTFIELD_BARRIER     = NEEDS_OBJECT_GC_WRITE_BARRIER;
1220  /** {@code true} if the VM requires write barriers on reference arraystore */
1221  public static final boolean  NEEDS_OBJECT_ASTORE_BARRIER       = NEEDS_OBJECT_GC_WRITE_BARRIER;
1222  /** {@code true} if the garbage collector requires read barriers on reference getfield or arrayload */
1223  private static final boolean NEEDS_OBJECT_GC_READ_BARRIER      = Selected.Constraints.get().needsObjectReferenceReadBarrier();
1224  /** {@code true} if the VM requires read barriers on reference getfield */
1225  public static final boolean  NEEDS_OBJECT_GETFIELD_BARRIER     = NEEDS_OBJECT_GC_READ_BARRIER;
1226  /** {@code true} if the VM requires read barriers on reference arrayload */
1227  public static final boolean  NEEDS_OBJECT_ALOAD_BARRIER        = NEEDS_OBJECT_GC_READ_BARRIER;
1228  /** {@code true} if the garbage collector supports the bulk copy operation */
1229  public static final boolean OBJECT_BULK_COPY_SUPPORTED         = !(NEEDS_OBJECT_ASTORE_BARRIER || NEEDS_OBJECT_ALOAD_BARRIER) || Selected.Constraints.get().objectReferenceBulkCopySupported();
1230
1231  /**
1232   * Barrier for writes of objects into fields of instances (i.e. putfield).
1233   *
1234   * @param ref the object which is the subject of the putfield
1235   * @param value the new value for the field
1236   * @param offset the offset of the field to be modified
1237   * @param locationMetadata an int that encodes the source location being modified
1238   */
1239  @Inline
1240  @Entrypoint
1241  public static void objectFieldWrite(Object ref, Object value, Offset offset, int locationMetadata) {
1242    if (NEEDS_OBJECT_GC_WRITE_BARRIER) {
1243      ObjectReference src = ObjectReference.fromObject(ref);
1244      Selected.Mutator.get().objectReferenceWrite(src, src.toAddress().plus(offset), ObjectReference.fromObject(value), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD);
1245    } else if (VM.VerifyAssertions)
1246      VM._assert(VM.NOT_REACHED);
1247  }
1248
1249  /**
1250   * Barrier for writes of objects into arrays (i.e. aastore).
1251   *
1252   * @param ref the array which is the subject of the astore
1253   * @param index the index into the array where the new reference
1254   * resides.  The index is the "natural" index into the array, for
1255   * example a[index].
1256   * @param value the value to be stored.
1257   */
1258  @Inline
1259  @Entrypoint
1260  public static void objectArrayWrite(Object[] ref, int index, Object value) {
1261    if (NEEDS_OBJECT_GC_WRITE_BARRIER) {
1262      ObjectReference array = ObjectReference.fromObject(ref);
1263      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS);
1264      Selected.Mutator.get().objectReferenceWrite(array, array.toAddress().plus(offset), ObjectReference.fromObject(value), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
1265    } else if (VM.VerifyAssertions)
1266      VM._assert(VM.NOT_REACHED);
1267  }
1268
1269  /**
1270   * Barrier for loads of objects from fields of instances (i.e. getfield).
1271   *
1272   * @param ref the object which is the subject of the getfield
1273   * @param offset the offset of the field to be read
1274   * @param locationMetadata an int that encodes the source location being read
1275   * @return The value read from the field.
1276   */
1277  @Inline
1278  @Entrypoint
1279  public static Object objectFieldRead(Object ref, Offset offset, int locationMetadata) {
1280    if (NEEDS_OBJECT_GC_READ_BARRIER) {
1281      ObjectReference src = ObjectReference.fromObject(ref);
1282      return Selected.Mutator.get().objectReferenceRead(src, src.toAddress().plus(offset), offset.toWord(), Word.fromIntZeroExtend(locationMetadata), INSTANCE_FIELD).toObject();
1283    } else if (VM.VerifyAssertions)
1284      VM._assert(VM.NOT_REACHED);
1285    return null;
1286  }
1287
1288  /**
1289   * Barrier for loads of objects from fields of arrays (i.e. aaload).
1290   *
1291   * @param ref the array containing the reference.
1292   * @param index the index into the array were the reference resides.
1293   * @return the value read from the array
1294   */
1295  @Inline
1296  @Entrypoint
1297  public static Object objectArrayRead(Object[] ref, int index) {
1298    if (NEEDS_OBJECT_GC_READ_BARRIER) {
1299      ObjectReference array = ObjectReference.fromObject(ref);
1300      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS);
1301      return Selected.Mutator.get().objectReferenceRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT).toObject();
1302    } else if (VM.VerifyAssertions)
1303      VM._assert(VM.NOT_REACHED);
1304    return null;
1305  }
1306
1307  /**
1308   * Barrier for a bulk copy of objects (i.e. in an array copy).
1309   *
1310   * @param src The source array
1311   * @param srcOffset The starting source offset
1312   * @param dst The destination array
1313   * @param dstOffset The starting destination offset
1314   * @param bytes The number of bytes to be copied
1315   */
1316  @Inline
1317  public static void objectBulkCopy(Object[] src, Offset srcOffset, Object[] dst, Offset dstOffset, int bytes) {
1318    if (VM.VerifyAssertions) VM._assert(OBJECT_BULK_COPY_SUPPORTED);
1319
1320    if (!Selected.Mutator.get().objectReferenceBulkCopy(ObjectReference.fromObject(src), srcOffset, ObjectReference.fromObject(dst), dstOffset, bytes)) {
1321      Memory.alignedWordCopy(Magic.objectAsAddress(dst).plus(dstOffset), Magic.objectAsAddress(src).plus(srcOffset), bytes);
1322    }
1323  }
1324
1325
1326  /** {@code true} if the selected plan requires write barriers on reference putstatic */
1327  private static final boolean NEEDS_OBJECT_GC_PUTSTATIC_BARRIER = Selected.Constraints.get().needsObjectReferenceNonHeapWriteBarrier();
1328  /** {@code true} if the selected plan requires write barriers on reference putstatic */
1329  public static final boolean  NEEDS_OBJECT_PUTSTATIC_BARRIER    = NEEDS_OBJECT_GC_PUTSTATIC_BARRIER;
1330  /** {@code true} if the selected plan requires read barriers on reference getstatic */
1331  private static final boolean NEEDS_OBJECT_GC_GETSTATIC_BARRIER = Selected.Constraints.get().needsObjectReferenceNonHeapReadBarrier();
1332  /** {@code true} if the selected plan requires read barriers on reference getstatic */
1333  public static final boolean  NEEDS_OBJECT_GETSTATIC_BARRIER    = NEEDS_OBJECT_GC_GETSTATIC_BARRIER;
1334
1335  /**
1336   * Barrier for writes of objects from statics (eg putstatic)
1337   *
1338   * @param value the new value to be stored
1339   * @param offset the offset of the field to be modified
1340   * @param locationMetadata an int that encodes the source location being modified
1341   */
1342  @Inline
1343  @Entrypoint
1344  public static void objectStaticWrite(Object value, Offset offset, int locationMetadata) {
1345    if (NEEDS_OBJECT_GC_PUTSTATIC_BARRIER) {
1346      ObjectReference src = ObjectReference.fromObject(Magic.getJTOC());
1347      Selected.Mutator.get().objectReferenceNonHeapWrite(src.toAddress().plus(offset),
1348          ObjectReference.fromObject(value),
1349          offset.toWord(),
1350          Word.fromIntZeroExtend(locationMetadata));
1351    } else if (VM.VerifyAssertions)
1352      VM._assert(VM.NOT_REACHED);
1353  }
1354
1355  /**
1356   * Barrier for loads of objects from statics (i.e. getstatic)
1357   *
1358   * @param offset the offset of the field to be modified
1359   * @param locationMetadata an int that encodes the source location being read
1360   * @return the value read from the field
1361   */
1362  @Inline
1363  @Entrypoint
1364  public static Object objectStaticRead(Offset offset, int locationMetadata) {
1365    if (NEEDS_OBJECT_GC_GETSTATIC_BARRIER) {
1366      ObjectReference src = ObjectReference.fromObject(Magic.getJTOC());
1367      return Selected.Mutator.get().objectReferenceNonHeapRead(
1368          src.toAddress().plus(offset),
1369          offset.toWord(),
1370          Word.fromIntZeroExtend(locationMetadata)).toObject();
1371    } else if (VM.VerifyAssertions)
1372      VM._assert(VM.NOT_REACHED);
1373    return null;
1374  }
1375
1376
1377  /**
1378   * Barrier for conditional compare and exchange of reference fields.
1379   *
1380   * @param ref the object which is the subject of the compare and exchanges
1381   * @param offset the offset of the field to be modified
1382   * @param old the old value to swap out
1383   * @param value the new value for the field
1384   * @return {@code true} if and only if the swap was successful
1385   */
1386  @Inline
1387  public static boolean objectTryCompareAndSwap(Object ref, Offset offset, Object old, Object value) {
1388    if (NEEDS_OBJECT_GC_WRITE_BARRIER || NEEDS_OBJECT_GC_READ_BARRIER) {
1389      ObjectReference src = ObjectReference.fromObject(ref);
1390      return Selected.Mutator.get().objectReferenceTryCompareAndSwap(src,
1391          src.toAddress().plus(offset),
1392          ObjectReference.fromObject(old),
1393          ObjectReference.fromObject(value),
1394          offset.toWord(),
1395          Word.zero(), // do not have location metadata
1396          INSTANCE_FIELD);
1397    } else if (VM.VerifyAssertions)
1398      VM._assert(VM.NOT_REACHED);
1399    return false;
1400  }
1401}