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.mmtk.utility; 014 015import org.mmtk.vm.VM; 016import org.vmmagic.pragma.Inline; 017import org.vmmagic.pragma.Uninterruptible; 018import org.vmmagic.unboxed.ObjectReference; 019import org.vmmagic.unboxed.Word; 020 021/** 022 * This class provides generic support for object forwarding, which is specific 023 * to a few policies that support copying. The broad idea is two-fold: 1) the 024 * two low-order bits of the GC byte (which are also the two low-order bits of 025 * the header word) are used to indicate whether an object has been forwarded 026 * or is being forwarded, and 2) if an object has been forwarded then the entire 027 * header word of the dead object is used to store a pointer to the forwarded 028 * pointer. This is a standard implementation of forwarding.<p> 029 * 030 * The two lowest order bits are used for object forwarding because forwarding 031 * generally must steal the unused two low order bits of the forwarding pointer. 032 */ 033@Uninterruptible 034public class ForwardingWord { 035 /* 036 * The forwarding process uses three states to deal with a GC race: 037 * 1. !FORWARDED: Unforwarded 038 * 2. BEING_FORWARDED: Being forwarded (forwarding is underway) 039 * 3. FORWARDED: Forwarded 040 */ 041 042 /** 043 * If this bit pattern is set, the forwarding of this object has not been 044 * triggered yet. 045 */ 046 private static final byte FORWARDING_NOT_TRIGGERED_YET = 0; // ...00 047 /** If this bit is set, then forwarding of this object is incomplete */ 048 private static final byte BEING_FORWARDED = 2; // ...10 049 /** If this bit is set, then forwarding of this object has commenced */ 050 private static final byte FORWARDED = 3; // ...11 051 /** This mask is used to reveal which state this object is in with respect to forwarding */ 052 public static final byte FORWARDING_MASK = 3; // ...11 053 054 public static final int FORWARDING_BITS = 2; 055 056 057 /** 058 * Either return the forwarding pointer if the object is already 059 * forwarded (or being forwarded) or write the bit pattern that 060 * indicates that the object is being forwarded 061 * 062 * @param object The object to be forwarded 063 * @return The forwarding pointer for the object if it has already 064 * been forwarded. 065 */ 066 @Inline 067 public static Word attemptToForward(ObjectReference object) { 068 Word oldValue; 069 do { 070 oldValue = VM.objectModel.prepareAvailableBits(object); 071 if ((byte) (oldValue.toInt() & FORWARDING_MASK) != FORWARDING_NOT_TRIGGERED_YET) 072 return oldValue; 073 } while (!VM.objectModel.attemptAvailableBits(object, oldValue, 074 oldValue.or(Word.fromIntZeroExtend(BEING_FORWARDED)))); 075 return oldValue; 076 } 077 078 public static ObjectReference spinAndGetForwardedObject(ObjectReference object, Word statusWord) { 079 /* We must wait (spin) if the object is not yet fully forwarded */ 080 while ((statusWord.toInt() & FORWARDING_MASK) == BEING_FORWARDED) 081 statusWord = VM.objectModel.readAvailableBitsWord(object); 082 083 /* Now extract the object reference from the forwarding word and return it */ 084 if ((statusWord.toInt() & FORWARDING_MASK) == FORWARDED) 085 return statusWord.and(Word.fromIntZeroExtend(FORWARDING_MASK).not()).toAddress().toObjectReference(); 086 else 087 return object; 088 } 089 090 public static ObjectReference forwardObject(ObjectReference object, int allocator) { 091 ObjectReference newObject = VM.objectModel.copy(object, allocator); 092 VM.objectModel.writeAvailableBitsWord(object, newObject.toAddress().toWord().or(Word.fromIntZeroExtend(FORWARDED))); 093 return newObject; 094 } 095 096 /** 097 * Non-atomic write of forwarding pointer word (assumption, thread 098 * doing the set has done attempt to forward and owns the right to 099 * copy the object) 100 * 101 * @param object The object whose forwarding pointer is to be set 102 * @param ptr The forwarding pointer to be stored in the object's 103 * forwarding word 104 */ 105 @Inline 106 public static void setForwardingPointer(ObjectReference object, 107 ObjectReference ptr) { 108 VM.objectModel.writeAvailableBitsWord(object, ptr.toAddress().toWord().or(Word.fromIntZeroExtend(FORWARDED))); 109 } 110 111 /** 112 * Has an object been forwarded? 113 * 114 * @param object The object to be checked 115 * @return {@code true} if the object has been forwarded 116 */ 117 @Inline 118 public static boolean isForwarded(ObjectReference object) { 119 return (VM.objectModel.readAvailableByte(object) & FORWARDING_MASK) == FORWARDED; 120 } 121 122 /** 123 * Has an object been forwarded or is it being forwarded? 124 * 125 * @param object The object to be checked 126 * @return {@code true} if the object has been forwarded 127 */ 128 @Inline 129 public static boolean isForwardedOrBeingForwarded(ObjectReference object) { 130 return (VM.objectModel.readAvailableByte(object) & FORWARDING_MASK) != 0; 131 } 132 133 /** 134 * Has an object been forwarded or being forwarded? 135 * 136 * @param header The object header to be checked 137 * @return {@code true} if the object has been forwarded 138 */ 139 @Inline 140 public static boolean stateIsForwardedOrBeingForwarded(Word header) { 141 return (header.toInt() & FORWARDING_MASK) != 0; 142 } 143 144 /** 145 * Has an object been forwarded or being forwarded? 146 * 147 * @param header The object header to be checked 148 * @return {@code true} if the object has been forwarded 149 */ 150 @Inline 151 public static boolean stateIsBeingForwarded(Word header) { 152 return (header.toInt() & FORWARDING_MASK) == BEING_FORWARDED; 153 } 154 155 /** 156 * Clear the GC forwarding portion of the header for an object. 157 * 158 * @param object the object ref to the storage to be initialized 159 */ 160 @Inline 161 public static void clearForwardingBits(ObjectReference object) { 162 VM.objectModel.writeAvailableByte(object, (byte) (VM.objectModel.readAvailableByte(object) & ~FORWARDING_MASK)); 163 } 164 165 @Inline 166 public static ObjectReference extractForwardingPointer(Word forwardingWord) { 167 return forwardingWord.and(Word.fromIntZeroExtend(FORWARDING_MASK).not()).toAddress().toObjectReference(); 168 } 169}