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