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