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.mmtk.utility;
014
015 import org.mmtk.vm.VM;
016 import org.vmmagic.pragma.Inline;
017 import org.vmmagic.pragma.Uninterruptible;
018 import org.vmmagic.unboxed.ObjectReference;
019 import 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
034 public 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 /** If this bit is set, then forwarding of this object is incomplete */
042 private static final byte BEING_FORWARDED = 2; // ...10
043 /** If this bit is set, then forwarding of this object has commenced */
044 private static final byte FORWARDED = 3; // ...11
045 /** This mask is used to reveal which state this object is in with respect to forwarding */
046 public static final byte FORWARDING_MASK = 3; // ...11
047
048 public static final int FORWARDING_BITS = 2;
049
050
051 /**
052 * Either return the forwarding pointer if the object is already
053 * forwarded (or being forwarded) or write the bit pattern that
054 * indicates that the object is being forwarded
055 *
056 * @param object The object to be forwarded
057 * @return The forwarding pointer for the object if it has already
058 * been forwarded.
059 */
060 @Inline
061 public static Word attemptToForward(ObjectReference object) {
062 Word oldValue;
063 do {
064 oldValue = VM.objectModel.prepareAvailableBits(object);
065 if ((byte) (oldValue.toInt() & FORWARDING_MASK) == FORWARDED)
066 return oldValue;
067 } while (!VM.objectModel.attemptAvailableBits(object, oldValue,
068 oldValue.or(Word.fromIntZeroExtend(BEING_FORWARDED))));
069 return oldValue;
070 }
071
072 public static ObjectReference spinAndGetForwardedObject(ObjectReference object, Word statusWord) {
073 /* We must wait (spin) if the object is not yet fully forwarded */
074 while ((statusWord.toInt() & FORWARDING_MASK) == BEING_FORWARDED)
075 statusWord = VM.objectModel.readAvailableBitsWord(object);
076
077 /* Now extract the object reference from the forwarding word and return it */
078 if ((statusWord.toInt() & FORWARDING_MASK) == FORWARDED)
079 return statusWord.and(Word.fromIntZeroExtend(FORWARDING_MASK).not()).toAddress().toObjectReference();
080 else
081 return object;
082 }
083
084 public static ObjectReference forwardObject(ObjectReference object, int allocator) {
085 ObjectReference newObject = VM.objectModel.copy(object, allocator);
086 VM.objectModel.writeAvailableBitsWord(object, newObject.toAddress().toWord().or(Word.fromIntZeroExtend(FORWARDED)));
087 return newObject;
088 }
089
090 /**
091 * Non-atomic write of forwarding pointer word (assumption, thread
092 * doing the set has done attempt to forward and owns the right to
093 * copy the object)
094 *
095 * @param object The object whose forwarding pointer is to be set
096 * @param ptr The forwarding pointer to be stored in the object's
097 * forwarding word
098 */
099 @Inline
100 public static void setForwardingPointer(ObjectReference object,
101 ObjectReference ptr) {
102 VM.objectModel.writeAvailableBitsWord(object, ptr.toAddress().toWord().or(Word.fromIntZeroExtend(FORWARDED)));
103 }
104
105 /**
106 * Has an object been forwarded?
107 *
108 * @param object The object to be checked
109 * @return True if the object has been forwarded
110 */
111 @Inline
112 public static boolean isForwarded(ObjectReference object) {
113 return (VM.objectModel.readAvailableByte(object) & FORWARDING_MASK) == FORWARDED;
114 }
115
116 /**
117 * Has an object been forwarded or is it being forwarded?
118 *
119 * @param object The object to be checked
120 * @return True if the object has been forwarded
121 */
122 @Inline
123 public static boolean isForwardedOrBeingForwarded(ObjectReference object) {
124 return (VM.objectModel.readAvailableByte(object) & FORWARDING_MASK) != 0;
125 }
126
127 /**
128 * Has an object been forwarded or being forwarded?
129 *
130 * @param object The object to be checked
131 * @return True if the object has been forwarded
132 */
133 @Inline
134 public static boolean stateIsForwardedOrBeingForwarded(Word header) {
135 return (header.toInt() & FORWARDING_MASK) != 0;
136 }
137
138 /**
139 * Has an object been forwarded or being forwarded?
140 *
141 * @param object The object to be checked
142 * @return True if the object has been forwarded
143 */
144 @Inline
145 public static boolean stateIsBeingForwarded(Word header) {
146 return (header.toInt() & FORWARDING_MASK) == BEING_FORWARDED;
147 }
148
149 /**
150 * Clear the GC forwarding portion of the header for an object.
151 *
152 * @param object the object ref to the storage to be initialized
153 */
154 @Inline
155 public static void clearForwardingBits(ObjectReference object) {
156 VM.objectModel.writeAvailableByte(object, (byte) (VM.objectModel.readAvailableByte(object) & ~FORWARDING_MASK));
157 }
158
159 @Inline
160 public static ObjectReference extractForwardingPointer(Word forwardingWord) {
161 return forwardingWord.and(Word.fromIntZeroExtend(FORWARDING_MASK).not()).toAddress().toObjectReference();
162 }
163 }