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 */
013 package org.jikesrvm.mm.mmtk;
014
015 import org.jikesrvm.SizeConstants;
016 import org.jikesrvm.runtime.Magic;
017 import org.mmtk.vm.VM;
018
019 import org.vmmagic.unboxed.*;
020 import org.vmmagic.pragma.*;
021
022 @Uninterruptible
023 public class Barriers extends org.mmtk.vm.Barriers implements SizeConstants {
024 /**
025 * Perform the actual write of a boolean write barrier.
026 *
027 * @param objref The object that has the boolean field
028 * @param value The value that the slot will be updated to
029 * @param offset The offset from the ref
030 * @param location The FieldReference index to assist the store
031 * @param mode The context in which the write is occurring
032 */
033 @Inline
034 @Override
035 public final void booleanWrite(ObjectReference objref, boolean value, Word offset, Word location, int mode) {
036 Magic.setBooleanAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
037 }
038
039 /**
040 * Perform the actual read of a boolean read barrier.
041 *
042 * @param objref The object that has the boolean field
043 * @param offset The offset from the ref
044 * @param unused Unused
045 * @param mode The context in which the write is occurring
046 * @return the read value
047 */
048 @Inline
049 @Override
050 public final boolean booleanRead(ObjectReference objref, Word offset, Word location, int mode) {
051 return Magic.getByteAtOffset(objref.toObject(), offset.toOffset()) == 0;
052 }
053
054 /**
055 * Perform the actual write of a byte write barrier.
056 *
057 * @param objref The object that has the byte field
058 * @param value The value that the slot will be updated to
059 * @param offset The offset from the ref
060 * @param location The FieldReference index to assist the store
061 * @param mode The context in which the write is occurring
062 */
063 @Inline
064 @Override
065 public final void byteWrite(ObjectReference objref, byte value, Word offset, Word location, int mode) {
066 Magic.setByteAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
067 }
068
069 /**
070 * Perform the actual read of a byte read barrier.
071 *
072 * @param objref The object that has the byte field
073 * @param offset The offset from the ref
074 * @param unused Unused
075 * @param mode The context in which the write is occurring
076 * @return the read value
077 */
078 @Inline
079 @Override
080 public final byte byteRead(ObjectReference objref, Word offset, Word location, int mode) {
081 return Magic.getByteAtOffset(objref.toObject(), offset.toOffset());
082 }
083
084 /**
085 * Perform the actual write of a char write barrier.
086 *
087 * @param objref The object that has the char field
088 * @param value The value that the slot will be updated to
089 * @param offset The offset from the ref
090 * @param location The FieldReference index to assist the store
091 * @param mode The context in which the write is occurring
092 */
093 @Inline
094 @Override
095 public final void charWrite(ObjectReference objref, char value, Word offset, Word location, int mode) {
096 Magic.setCharAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
097 }
098
099 /**
100 * Perform the actual read of a char read barrier.
101 *
102 * @param objref The object that has the char field
103 * @param offset The offset from the ref
104 * @param unused Unused
105 * @param mode The context in which the write is occurring
106 * @return the read value
107 */
108 @Inline
109 @Override
110 public final char charRead(ObjectReference objref, Word offset, Word location, int mode) {
111 return Magic.getCharAtOffset(objref.toObject(), offset.toOffset());
112 }
113
114 /**
115 * Perform the actual write of a short write barrier.
116 *
117 * @param objref The object that has the short field
118 * @param value The value that the slot will be updated to
119 * @param offset The offset from the ref
120 * @param location The FieldReference index to assist the store
121 * @param mode The context in which the write is occurring
122 */
123 @Inline
124 @Override
125 public final void shortWrite(ObjectReference objref, short value, Word offset, Word location, int mode) {
126 Magic.setShortAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
127 }
128
129 /**
130 * Perform the actual read of a short read barrier.
131 *
132 * @param objref The object that has the short field
133 * @param offset The offset from the ref
134 * @param unused Unused
135 * @param mode The context in which the write is occurring
136 * @return the read value
137 */
138 @Inline
139 @Override
140 public final short shortRead(ObjectReference objref, Word offset, Word location, int mode) {
141 return Magic.getShortAtOffset(objref.toObject(), offset.toOffset());
142 }
143
144 /**
145 * Perform the actual write of a int write barrier.
146 *
147 * @param objref The object that has the int field
148 * @param value The value that the slot will be updated to
149 * @param offset The offset from the ref
150 * @param location The FieldReference index to assist the store
151 * @param mode The context in which the write is occurring
152 */
153 @Inline
154 @Override
155 public final void intWrite(ObjectReference objref, int value, Word offset, Word location, int mode) {
156 Magic.setIntAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
157 }
158
159 /**
160 * Perform the actual read of a int read barrier.
161 *
162 * @param objref The object that has the int field
163 * @param offset The offset from the ref
164 * @param unused Unused
165 * @param mode The context in which the write is occurring
166 * @return the read value
167 */
168 @Inline
169 @Override
170 public final int intRead(ObjectReference objref, Word offset, Word location, int mode) {
171 return Magic.getIntAtOffset(objref.toObject(), offset.toOffset());
172 }
173
174 /**
175 * Attempt an atomic compare and exchange in a write barrier sequence.
176 *
177 * @param objref The object that has the int field
178 * @param expected The old int to be swapped out
179 * @param newValue the new int
180 * @param offset The offset from the ref
181 * @param unused Unused
182 * @param mode The context in which the write is occurring
183 * @return True if the compare and swap was successful
184 */
185 @Override
186 public boolean intTryCompareAndSwap(ObjectReference objref, int expected, int newValue, Word offset, Word unused, int mode) {
187 int oldValue;
188 do {
189 oldValue = Magic.prepareInt(objref, offset.toOffset());
190 if (oldValue != expected) return false;
191 } while (!Magic.attemptInt(objref, offset.toOffset(), oldValue, newValue));
192 return true;
193 }
194
195 /**
196 * Perform the actual write of a long write barrier.
197 *
198 * @param objref The object that has the long field
199 * @param value The value that the slot will be updated to
200 * @param offset The offset from the ref
201 * @param location The FieldReference index to assist the store
202 * @param mode The context in which the write is occurring
203 */
204 @Inline
205 @Override
206 public final void longWrite(ObjectReference objref, long value, Word offset, Word location, int mode) {
207 Magic.setLongAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
208 }
209
210 /**
211 * Perform the actual read of a long read barrier.
212 *
213 * @param objref The object that has the long field
214 * @param offset The offset from the ref
215 * @param unused Unused
216 * @param mode The context in which the write is occurring
217 * @return the read value
218 */
219 @Inline
220 @Override
221 public final long longRead(ObjectReference objref, Word offset, Word location, int mode) {
222 return Magic.getLongAtOffset(objref.toObject(), offset.toOffset());
223 }
224
225 /**
226 * Attempt an atomic compare and exchange in a write barrier sequence.
227 *
228 * @param objref The object that has the long field
229 * @param expected The old long to be swapped out
230 * @param newValue the new long
231 * @param offset The offset from the ref
232 * @param unused Unused
233 * @param mode The context in which the write is occurring
234 * @return True if the compare and swap was successful
235 */
236 @Override
237 public boolean longTryCompareAndSwap(ObjectReference objref, long expected, long newValue, Word offset, Word unused, int mode) {
238 long oldValue;
239 do {
240 oldValue = Magic.prepareLong(objref, offset.toOffset());
241 if (oldValue != expected) return false;
242 } while (!Magic.attemptLong(objref, offset.toOffset(), oldValue, newValue));
243 return true;
244 }
245
246 /**
247 * Perform the actual write of a float write barrier.
248 *
249 * @param objref The object that has the float field
250 * @param value The value that the slot will be updated to
251 * @param offset The offset from the ref
252 * @param location The FieldReference index to assist the store
253 * @param mode The context in which the write is occurring
254 */
255 @Inline
256 @Override
257 public final void floatWrite(ObjectReference objref, float value, Word offset, Word location, int mode) {
258 Magic.setFloatAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
259 }
260
261 /**
262 * Perform the actual read of a float read barrier.
263 *
264 * @param objref The object that has the float field
265 * @param offset The offset from the ref
266 * @param unused Unused
267 * @param mode The context in which the write is occurring
268 * @return the read value
269 */
270 @Inline
271 @Override
272 public final float floatRead(ObjectReference objref, Word offset, Word location, int mode) {
273 return Magic.getFloatAtOffset(objref.toObject(), offset.toOffset());
274 }
275
276 /**
277 * Perform the actual write of a double write barrier.
278 *
279 * @param objref The object that has the double field
280 * @param value The value that the slot will be updated to
281 * @param offset The offset from the ref
282 * @param location The FieldReference index to assist the store
283 * @param mode The context in which the write is occurring
284 */
285 @Inline
286 @Override
287 public final void doubleWrite(ObjectReference objref, double value, Word offset, Word location, int mode) {
288 Magic.setDoubleAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
289 }
290
291 /**
292 * Perform the actual read of a double read barrier.
293 *
294 * @param objref The object that has the double field
295 * @param offset The offset from the ref
296 * @param unused Unused
297 * @param mode The context in which the write is occurring
298 * @return the read value
299 */
300 @Inline
301 @Override
302 public final double doubleRead(ObjectReference objref, Word offset, Word location, int mode) {
303 return Magic.getDoubleAtOffset(objref.toObject(), offset.toOffset());
304 }
305
306 /**
307 * Perform the actual write of an object reference write barrier.
308 *
309 * @param objref The object that has the reference field
310 * @param value The value that the slot will be updated to
311 * @param offset The offset from the ref
312 * @param location The index of the FieldReference
313 * @param mode The context in which the write is occurring
314 */
315 @Inline
316 @Override
317 public final void objectReferenceWrite(ObjectReference objref, ObjectReference value, Word offset, Word location, int mode) {
318 Magic.setObjectAtOffset(objref.toObject(), offset.toOffset(), value.toObject(), location.toInt());
319 }
320
321 /**
322 * Perform the actual read of an object reference read barrier.
323 *
324 * @param objref The object that has the reference field
325 * @param offset The offset from the ref
326 * @param location The index of the FieldReference
327 * @param mode The context in which the write is occurring
328 * @return the object reference read value
329 */
330 @Inline
331 @Override
332 public final ObjectReference objectReferenceRead(ObjectReference objref, Word offset, Word location, int mode) {
333 return ObjectReference.fromObject(Magic.getObjectAtOffset(objref.toObject(), offset.toOffset(), location.toInt()));
334 }
335
336 /**
337 * Perform the actual write of the non-heap write barrier. This is
338 * used when the store is not to an object, but to a non-heap location
339 * such as statics or the stack.
340 * @param target The value that the slot will be updated to
341 * @param unusedA The offset from the ref
342 * @param unusedB Unused
343 * @param ref The object that has the reference field
344 */
345 @Inline
346 @Override
347 public final void objectReferenceNonHeapWrite(Address slot, ObjectReference target, Word unusedA, Word unusedB) {
348 slot.store(target);
349 }
350
351 /**
352 * Atomically write a reference field of an object or array and return
353 * the old value of the reference field.
354 *
355 * @param objref The object that has the reference field
356 * @param target The value that the slot will be updated to
357 * @param offset The offset from the ref
358 * @param unused Unused
359 * @param mode The context in which the write is occurring
360 * @return The value that was replaced by the write.
361 */
362 @Inline
363 @Override
364 public final ObjectReference objectReferenceAtomicWrite(ObjectReference objref, ObjectReference target, Word offset, Word unused, int mode) {
365 Object obj = objref.toObject();
366 Object newObject = target.toObject();
367 Object oldObject;
368 do {
369 oldObject = Magic.prepareObject(obj, offset.toOffset());
370 } while (!Magic.attemptObject(obj, offset.toOffset(), oldObject, newObject));
371 return ObjectReference.fromObject(oldObject);
372 }
373
374 /**
375 * Attempt an atomic compare and exchange in a write barrier sequence.
376 *
377 * @param objref The object that has the reference field
378 * @param old The old reference to be swapped out
379 * @param target The value that the slot will be updated to
380 * @param offset The offset from the ref
381 * @param unused Unused
382 * @param mode The context in which the write is occurring
383 * @return True if the compare and swap was successful
384 */
385 @Inline
386 @Override
387 public final boolean objectReferenceTryCompareAndSwap(ObjectReference objref, ObjectReference old, ObjectReference target, Word offset, Word unused, int mode) {
388 Object oldValue;
389 do {
390 oldValue = Magic.prepareObject(objref, offset.toOffset());
391 if (oldValue != old) return false;
392 } while (!Magic.attemptObject(objref, offset.toOffset(), oldValue, target));
393 return true;
394 }
395
396 /**
397 * Perform the actual write of the write barrier, writing the value as a raw Word.
398 *
399 * @param ref The object that has the Word field
400 * @param target The value that the slot will be updated to
401 * @param offset The offset from the ref
402 * @param location The index of the FieldReference
403 * @param mode The context in which the write is occurring
404 */
405 @Inline
406 @Override
407 public final void wordWrite(ObjectReference ref, Word target,
408 Word offset, Word location, int mode) {
409 Magic.setWordAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
410 }
411
412 /**
413 * Atomically write a raw reference field of an object or array and return
414 * the old value of the reference field.
415 *
416 * @param ref The object that has the Word field
417 * @param target The value that the slot will be updated to
418 * @param offset The offset from the ref
419 * @param unused Unused
420 * @param mode The context in which the write is occurring
421 * @return The value that was replaced by the write.
422 */
423 @Inline
424 @Override
425 public final Word wordAtomicWrite(ObjectReference ref, Word target,
426 Word offset, Word unused, int mode) {
427 Word oldValue;
428 do {
429 oldValue = Magic.prepareWord(ref.toObject(), offset.toOffset());
430 } while (!Magic.attemptWord(ref.toObject(), offset.toOffset(), oldValue, target));
431 return oldValue;
432 }
433
434 /**
435 * Attempt an atomic compare and exchange in a write barrier sequence.
436 *
437 * @param ref The object that has the Word field
438 * @param old The old Word to be swapped out
439 * @param target The value that the slot will be updated to
440 * @param offset The offset from the ref
441 * @param unused Unused
442 * @param mode The context in which the write is occurring
443 * @return True if the compare and swap was successful
444 */
445 @Inline
446 @Override
447 public final boolean wordTryCompareAndSwap(ObjectReference ref, Word old, Word target,
448 Word offset, Word unused, int mode) {
449 do {
450 Word currentValue = Magic.prepareWord(ref, offset.toOffset());
451 if (currentValue != old) return false;
452 } while (!Magic.attemptWord(ref, offset.toOffset(), old, target));
453 return true;
454 }
455
456 /**
457 * Perform the actual read of the read barrier, returning the value as a raw Word.
458 *
459 * @param ref The object that has the Word field
460 * @param offset The offset from the ref
461 * @param location The index of the FieldReference
462 * @param mode The context in which the write is occurring
463 * @return the read value
464 */
465 @Inline
466 @Override
467 public final Word wordRead(ObjectReference ref,
468 Word offset, Word location, int mode) {
469 return Magic.getWordAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
470 }
471
472 /**
473 * Perform the actual write of the write barrier, writing the value as a raw Address.
474 *
475 * @param ref The object that has the Address field
476 * @param target The value that the slot will be updated to
477 * @param offset The offset from the ref
478 * @param location The index of the FieldReference
479 * @param mode The context in which the write is occurring
480 */
481 @Inline
482 @Override
483 public final void addressWrite(ObjectReference ref, Address target,
484 Word offset, Word location, int mode) {
485 Magic.setAddressAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
486 }
487
488 /**
489 * Perform the actual read of the read barrier, returning the value as a raw Address.
490 *
491 * @param ref The object that has the Address field
492 * @param offset The offset from the ref
493 * @param location The index of the FieldReference
494 * @param mode The context in which the write is occurring
495 * @return the read value
496 */
497 @Inline
498 @Override
499 public final Address addressRead(ObjectReference ref,
500 Word offset, Word location, int mode) {
501 return Magic.getAddressAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
502 }
503
504 /**
505 * Attempt an atomic compare and exchange in a write barrier sequence.
506 *
507 * @param objref The object that has the Address field
508 * @param expected The old Address to be swapped out
509 * @param newValue the new Address
510 * @param offset The offset from the ref
511 * @param unused Unused
512 * @param mode The context in which the write is occurring
513 * @return True if the compare and swap was successful
514 */
515 @Override
516 public boolean addressTryCompareAndSwap(ObjectReference objref, Address expected, Address newValue, Word offset, Word unused, int mode) {
517 Address oldValue;
518 do {
519 oldValue = Magic.prepareAddress(objref, offset.toOffset());
520 if (oldValue != expected) return false;
521 } while (!Magic.attemptAddress(objref, offset.toOffset(), oldValue, newValue));
522 return true;
523 }
524
525 /**
526 * Perform the actual write of the write barrier, writing the value as a raw Offset.
527 *
528 * @param ref The object that has the Offset field
529 * @param target The value that the slot will be updated to
530 * @param offset The offset from the ref
531 * @param location The index of the FieldReference
532 * @param mode The context in which the write is occurring
533 */
534 @Inline
535 @Override
536 public final void offsetWrite(ObjectReference ref, Offset target,
537 Word offset, Word location, int mode) {
538 Magic.setOffsetAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
539 }
540
541 /**
542 * Perform the actual read of the read barrier, returning the value as a raw Offset.
543 *
544 * @param ref The object that has the Offset field
545 * @param offset The offset from the ref
546 * @param location The index of the FieldReference
547 * @param mode The context in which the write is occurring
548 * @return the read value
549 */
550 @Inline
551 @Override
552 public final Offset offsetRead(ObjectReference ref,
553 Word offset, Word location, int mode) {
554 return Magic.getOffsetAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
555 }
556
557 /**
558 * Perform the actual write of the write barrier, writing the value as a raw Extent.
559 *
560 * @param ref The object that has the Extent field
561 * @param target The value that the slot will be updated to
562 * @param offset The offset from the ref
563 * @param location The index of the FieldReference
564 * @param mode The context in which the write is occurring
565 */
566 @Inline
567 @Override
568 public final void extentWrite(ObjectReference ref, Extent target,
569 Word offset, Word location, int mode) {
570 Magic.setExtentAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
571 }
572
573 /**
574 * Perform the actual read of the read barrier, returning the value as a raw Extent.
575 *
576 * @param ref The object that has the Extent field
577 * @param offset The offset from the ref
578 * @param location The index of the FieldReference
579 * @param mode The context in which the write is occurring
580 * @return the read value
581 */
582 @Inline
583 @Override
584 public final Extent extentRead(ObjectReference ref,
585 Word offset, Word location, int mode) {
586 return Magic.getExtentAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
587 }
588
589 /**
590 * Sets an element of an object array without invoking any write
591 * barrier. This method is called by the Map class to ensure
592 * potentially-allocation-triggering write barriers do not occur in
593 * allocation slow path code.
594 *
595 * @param dst the destination array
596 * @param index the index of the element to set
597 * @param value the new value for the element
598 */
599 @UninterruptibleNoWarn
600 @Override
601 public final void objectArrayStoreNoGCBarrier(Object[] dst, int index, Object value) {
602 if (org.jikesrvm.VM.runningVM) {
603 Address base = ObjectReference.fromObject(dst).toAddress();
604 Address slot = base.plus(Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS));
605 VM.activePlan.global().storeObjectReference(slot, ObjectReference.fromObject(value));
606 } else {
607 dst[index] = value;
608 }
609 }
610 }