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 }