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