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.policy;
014
015 import org.mmtk.plan.Plan;
016 import org.mmtk.plan.TransitiveClosure;
017 import org.mmtk.utility.heap.MonotonePageResource;
018 import org.mmtk.utility.heap.VMRequest;
019 import org.mmtk.utility.Constants;
020 import org.mmtk.utility.HeaderByte;
021
022 import org.mmtk.vm.VM;
023
024 import org.vmmagic.unboxed.*;
025 import org.vmmagic.pragma.*;
026
027 /**
028 * This class implements tracing for a simple immortal collection
029 * policy. Under this policy all that is required is for the
030 * "collector" to propagate marks in a liveness trace. It does not
031 * actually collect. This class does not hold any state, all methods
032 * are static.
033 */
034 @Uninterruptible public final class ImmortalSpace extends Space
035 implements Constants {
036
037 /****************************************************************************
038 *
039 * Class variables
040 */
041
042 /**
043 *
044 */
045 static final byte GC_MARK_BIT_MASK = 1;
046 private static final int META_DATA_PAGES_PER_REGION = CARD_META_PAGES_PER_REGION;
047
048 /****************************************************************************
049 *
050 * Instance variables
051 */
052
053 /**
054 *
055 */
056 private byte markState = 0; // when GC off, the initialization value
057
058 /****************************************************************************
059 *
060 * Initialization
061 */
062
063 /**
064 * The caller specifies the region of virtual memory to be used for
065 * this space. If this region conflicts with an existing space,
066 * then the constructor will fail.
067 *
068 * @param name The name of this space (used when printing error messages etc)
069 * @param vmRequest An object describing the virtual memory requested.
070 */
071 public ImmortalSpace(String name, VMRequest vmRequest) {
072 this(name, true, vmRequest);
073 }
074
075 /**
076 * The caller specifies the region of virtual memory to be used for
077 * this space. If this region conflicts with an existing space,
078 * then the constructor will fail.
079 *
080 * @param name The name of this space (used when printing error messages etc)
081 * @param zeroed if true, allocations return zeroed memory.
082 * @param vmRequest An object describing the virtual memory requested.
083 */
084 public ImmortalSpace(String name, boolean zeroed, VMRequest vmRequest) {
085 super(name, false, true, zeroed, vmRequest);
086 if (vmRequest.isDiscontiguous()) {
087 pr = new MonotonePageResource(this, META_DATA_PAGES_PER_REGION);
088 } else {
089 pr = new MonotonePageResource(this, start, extent, META_DATA_PAGES_PER_REGION);
090 }
091 }
092
093 /** @return the current mark state */
094 @Inline
095 public Word getMarkState() { return Word.fromIntZeroExtend(markState); }
096
097 /****************************************************************************
098 *
099 * Object header manipulations
100 */
101
102 /**
103 * Initialize the object header post-allocation. We need to set the mark state
104 * correctly and set the logged bit if necessary.
105 *
106 * @param object The newly allocated object instance whose header we are initializing
107 */
108 public void initializeHeader(ObjectReference object) {
109 byte oldValue = VM.objectModel.readAvailableByte(object);
110 byte newValue = (byte) ((oldValue & GC_MARK_BIT_MASK) | markState);
111 if (HeaderByte.NEEDS_UNLOGGED_BIT) newValue |= HeaderByte.UNLOGGED_BIT;
112 VM.objectModel.writeAvailableByte(object, newValue);
113 }
114
115 /**
116 * Used to mark boot image objects during a parallel scan of objects during GC
117 * Returns {@code true} if marking was done.
118 */
119 @Inline
120 private static boolean testAndMark(ObjectReference object, byte value) {
121 Word oldValue;
122 do {
123 oldValue = VM.objectModel.prepareAvailableBits(object);
124 byte markBit = (byte) (oldValue.toInt() & GC_MARK_BIT_MASK);
125 if (markBit == value) return false;
126 } while (!VM.objectModel.attemptAvailableBits(object, oldValue,
127 oldValue.xor(Word.fromIntZeroExtend(GC_MARK_BIT_MASK))));
128 return true;
129 }
130
131 /**
132 * Trace a reference to an object under an immortal collection
133 * policy. If the object is not already marked, enqueue the object
134 * for subsequent processing. The object is marked as (an atomic)
135 * side-effect of checking whether already marked.
136 *
137 * @param trace The trace being conducted.
138 * @param object The object to be traced.
139 */
140 @Override
141 @Inline
142 public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
143 if (testAndMark(object, markState))
144 trace.processNode(object);
145 return object;
146 }
147
148 /**
149 * Prepare for a new collection increment. For the immortal
150 * collector we must flip the state of the mark bit between
151 * collections.
152 */
153 public void prepare() {
154 markState = (byte) (GC_MARK_BIT_MASK - markState);
155 }
156
157 public void release() {}
158
159 /**
160 * Release an allocated page or pages. In this case we do nothing
161 * because we only release pages enmasse.
162 *
163 * @param start The address of the start of the page or pages
164 */
165 @Override
166 @Inline
167 public void release(Address start) {
168 if (VM.VERIFY_ASSERTIONS)
169 VM.assertions._assert(false); // this policy only releases pages enmasse
170 }
171
172 @Override
173 @Inline
174 public boolean isLive(ObjectReference object) {
175 return true;
176 }
177
178 /**
179 * Returns if the object in question is currently thought to be reachable.
180 * This is done by comparing the mark bit to the current mark state. For the
181 * immortal collector reachable and live are different, making this method
182 * necessary.
183 *
184 * @param object The address of an object in immortal space to test
185 * @return <code>true</code> if <code>ref</code> may be a reachable object (e.g., having
186 * the current mark state). While all immortal objects are live,
187 * some may be unreachable.
188 */
189 @Override
190 public boolean isReachable(ObjectReference object) {
191 if (Plan.SCAN_BOOT_IMAGE && this == Plan.vmSpace)
192 return true; // ignore boot image "reachabilty" if we're not tracing it
193 else
194 return (VM.objectModel.readAvailableByte(object) & GC_MARK_BIT_MASK) == markState;
195 }
196 }