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.gcspy;
014
015 import org.mmtk.utility.Log;
016 import org.mmtk.vm.gcspy.Util;
017
018 import org.vmmagic.unboxed.*;
019 import org.vmmagic.pragma.*;
020
021
022
023 /**
024 * This class is an abstraction of a contiguous region of a Space. For
025 * example, a semispace collector might choose to model the heap as a
026 * single Space, but within that Space it could model each semispace by
027 * a Subspace.<p>
028 * Subspace provides a number of useful facilities to many drivers, and
029 * is useful even if the Space comprises just a single contiguous region.<p>
030 *
031 * A subspace keeps track of the start and end address of the region,
032 * the index of its first block, the size of the blocks in this space,
033 * and the number of blocks in this subspace.
034 */
035 @Uninterruptible public class Subspace {
036
037 /** start address of the subspace. A subspace spans the address
038 * range <code>[start_, end_)</code> **/
039 private Address start_;
040 /** end address of the subspace. A subspace spans the address
041 * range <code>[start_, end_)</code> **/
042 private Address end_;
043 /** The index of the block in which {@code start_} lies */
044 private int firstIndex_;
045 /** the block size */
046 private int blockSize_;
047 /** the number of blocks in this space */
048 private int blockNum_;
049
050 private static final boolean DEBUG = false;
051
052 /**
053 * Create a new subspace
054 *
055 * @param start The address of the start of the subspace
056 * @param end The address of the end of the subspace
057 * @param firstIndex The index of the first block of the subspace
058 * @param blockSize The size of blocks in this space
059 * @param blockNum The number of blocks in this subspace
060 */
061 public Subspace(Address start,
062 Address end,
063 int firstIndex,
064 int blockSize,
065 int blockNum) {
066 reset(start, end, firstIndex, blockSize, blockNum);
067 }
068
069
070 //------------------Methods to reset a subspace----------------------
071
072 /**
073 * Reset a subspace.
074 *
075 * @param start The address of the start of the subspace
076 * @param end The address of the end of the subspace
077 * @param firstIndex The index of the first block of the subspace
078 * @param blockSize The size of blocks in this subspace
079 * @param blockNum The number of blocks in this subspace
080 */
081 private void reset(Address start,
082 Address end,
083 int firstIndex,
084 int blockSize,
085 int blockNum) {
086 //TODO sanity check on addresses and block size and number
087 reset(start, end, firstIndex, blockNum);
088 blockSize_ = blockSize;
089
090 if (DEBUG) dump();
091 }
092
093 /**
094 * Reset a new subspace
095 *
096 * @param start The address of the start of the subspace
097 * @param end The address of the end of the subspace
098 * @param firstIndex The index of the first block of the subspace
099 * @param blockNum The number of blocks in this subspace
100 */
101 public void reset(Address start,
102 Address end,
103 int firstIndex,
104 int blockNum) {
105 start_ = start;
106 end_ = end;
107 firstIndex_ = firstIndex;
108 blockNum_ = blockNum;
109 }
110
111 /**
112 * Reset a new subspace.
113 *
114 * @param start The address of the start of the subspace
115 * @param end The address of the end of the subspace
116 * @param blockNum The number of blocks in this subspace
117 */
118 public void reset(Address start, Address end, int blockNum) {
119 start_ = start;
120 end_ = end;
121 blockNum_ = blockNum;
122 }
123
124 /**
125 * Reset a new subspace.
126 *
127 * @param firstIndex The index of the first block of the subspace
128 * @param blockNum The number of blocks in this subspace
129 */
130 public void reset(int firstIndex, int blockNum) {
131 firstIndex_ = firstIndex;
132 blockNum_ = blockNum;
133 }
134
135
136 //----------------Facilities to query a subspace-----------------
137
138 /**
139 * Is an index in the range of this subspace?
140 *
141 * @param index The index of the block
142 * @return {@code true} if this block lies in this subspace
143 */
144 public boolean indexInRange(int index) {
145 return index >= firstIndex_ &&
146 index < firstIndex_ + blockNum_;
147 }
148
149 /**
150 * Is address in the range of this subspace?
151 *
152 * @param addr An address
153 * @return {@code true} if this address is in a block in this subspace
154 */
155 public boolean addressInRange(Address addr) {
156 return addr.GE(start_) && addr.LT(end_);
157 }
158
159
160 /**
161 * Get the block index from an address
162 *
163 * @param addr The address
164 * @return The index of the block holding this address
165 */
166 public int getIndex(Address addr) {
167 if (DEBUG) {
168 Log.write("start_ ", start_);
169 Log.write(" end_ ", end_);
170 Log.write(" blockSize_ ", blockSize_);
171 Log.write(" firstIndex_ ", firstIndex_);
172 Log.write(" + ", addr.diff(start_).toInt() / blockSize_);
173 Log.writeln(" addr ", addr);
174 }
175 return firstIndex_ + addr.diff(start_).toInt() / blockSize_;
176 }
177
178 /**
179 * Get the address of start of block from its index
180 *
181 * @param index The index of the block
182 * @return The address of the start of the block
183 */
184 public Address getAddress(int index) {
185 return start_.plus(index - firstIndex_ * blockSize_);
186 }
187
188 //--------------Accessors-------------------------
189
190 /**
191 * Get the start of the subspace
192 * @return The start of this subspace
193 */
194 public Address getStart() { return start_; }
195
196 /**
197 * Get the end of this subspace
198 * @return The address of the end of this subspace
199 */
200 public Address getEnd() { return end_; }
201
202 /**
203 * Get the first index of subspace
204 * @return the firstIndex of this subspace
205 */
206 public int getFirstIndex() { return firstIndex_; }
207
208 /**
209 * Get the blocksize for this subspace
210 * @return The size of a tile
211 */
212 public int getBlockSize() { return blockSize_; }
213
214 /**
215 * Get the number of tiles in this subspace
216 * @return The number of tiles in this subspace
217 */
218 public int getBlockNum() { return blockNum_; }
219
220 /**
221 * Calculate the space remaining in a block after this address
222 *
223 * @param addr the Address
224 * @return the remainder
225 */
226 public int spaceRemaining(Address addr) {
227 int nextIndex = getIndex(addr) + 1;
228 Address nextTile = start_.plus(blockSize_ * (nextIndex - firstIndex_));
229 return nextTile.diff(addr).toInt();
230 }
231
232 /**
233 * Dump a representation of the subspace
234 */
235 private void dump() {
236 Log.write("GCspy Subspace: ");
237 Util.dumpRange(start_, end_);
238 Log.writeln("\n -- firstIndex=", firstIndex_);
239 Log.writeln(" -- blockNum=", blockNum_);
240 }
241 }
242
243