/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.mmtk.utility.gcspy; import org.mmtk.utility.Log; import org.mmtk.vm.gcspy.Util; import org.vmmagic.unboxed.*; import org.vmmagic.pragma.*; /** * This class is an abstraction of a contiguous region of a Space. For * example, a semispace collector might choose to model the heap as a * single Space, but within that Space it could model each semispace by * a Subspace.<p> * Subspace provides a number of useful facilities to many drivers, and * is useful even if the Space comprises just a single contiguous region.<p> * * A subspace keeps track of the start and end address of the region, * the index of its first block, the size of the blocks in this space, * and the number of blocks in this subspace. */ @Uninterruptible public class Subspace { private Address start_; // The Subspace spans the address range [start_, end_) private Address end_; private int firstIndex_; // The index of the block in which start_ lies private int blockSize_; // The block size private int blockNum_; // The number of blocks in this space private static final boolean DEBUG = false; /** * Create a new subspace * * @param start The address of the start of the subspace * @param end The address of the end of the subspace * @param firstIndex The index of the first block of the subspace * @param blockSize The size of blocks in this space * @param blockNum The number of blocks in this subspace */ public Subspace(Address start, Address end, int firstIndex, int blockSize, int blockNum) { reset(start, end, firstIndex, blockSize, blockNum); } //------------------Methods to reset a subspace---------------------- /** * Reset a subspace. * * @param start The address of the start of the subspace * @param end The address of the end of the subspace * @param firstIndex The index of the first block of the subspace * @param blockSize The size of blocks in this subspace * @param blockNum The number of blocks in this subspace */ private void reset(Address start, Address end, int firstIndex, int blockSize, int blockNum) { //TODO sanity check on addresses and block size and number reset(start, end, firstIndex, blockNum); blockSize_ = blockSize; if (DEBUG) dump(); } /** * Reset a new subspace * * @param start The address of the start of the subspace * @param end The address of the end of the subspace * @param firstIndex The index of the first block of the subspace * @param blockNum The number of blocks in this subspace */ public void reset(Address start, Address end, int firstIndex, int blockNum) { start_ = start; end_ = end; firstIndex_ = firstIndex; blockNum_ = blockNum; } /** * Reset a new subspace. * * @param start The address of the start of the subspace * @param end The address of the end of the subspace * @param blockNum The number of blocks in this subspace */ public void reset(Address start, Address end, int blockNum) { start_ = start; end_ = end; blockNum_ = blockNum; } /** * Reset a new subspace. * * @param firstIndex The index of the first block of the subspace * @param blockNum The number of blocks in this subspace */ public void reset(int firstIndex, int blockNum) { firstIndex_ = firstIndex; blockNum_ = blockNum; } //----------------Facilities to query a subspace----------------- /** * Is an index in the range of this subspace? * * @param index The index of the block * @return true if this block lies in this subspace */ public boolean indexInRange(int index) { return index >= firstIndex_ && index < firstIndex_ + blockNum_; } /** * Is address in the range of this subspace? * * @param addr An address * @return true if this address is in a block in this subspace */ public boolean addressInRange(Address addr) { return addr.GE(start_) && addr.LT(end_); } /** * Get the block index from an address * * @param addr The address * @return The index of the block holding this address */ public int getIndex(Address addr) { if (DEBUG) { Log.write("start_ ", start_); Log.write(" end_ ", end_); Log.write(" blockSize_ ", blockSize_); Log.write(" firstIndex_ ", firstIndex_); Log.write(" + ", addr.diff(start_).toInt() / blockSize_); Log.writeln(" addr ", addr); } return firstIndex_ + addr.diff(start_).toInt() / blockSize_; } /** * Get the address of start of block from its index * * @param index The index of the block * @return The address of the start of the block */ public Address getAddress(int index) { return start_.plus(index - firstIndex_ * blockSize_); } //--------------Accessors------------------------- /** * Get the start of the subspace * @return The start of this subspace */ public Address getStart() { return start_; } /** * Get the end of this subspace * @return The address of the end of this subspace */ public Address getEnd() { return end_; } /** * Get the first index of subspace * @return the firstIndex of this subspace */ public int getFirstIndex() { return firstIndex_; } /** * Get the blocksize for this subspace * @return The size of a tile */ public int getBlockSize() { return blockSize_; } /** * Get the number of tiles in this subspace * @return The number of tiles in this subspace */ public int getBlockNum() { return blockNum_; } /** * Calculate the space remaining in a block after this address * * @param addr the Address * @return the remainder */ public int spaceRemaining(Address addr) { int nextIndex = getIndex(addr) + 1; Address nextTile = start_.plus(blockSize_ * (nextIndex - firstIndex_)); return nextTile.diff(addr).toInt(); } /** * Dump a representation of the subspace */ private void dump() { Log.write("GCspy Subspace: "); Util.dumpRange(start_, end_); Log.writeln("\n -- firstIndex=", firstIndex_); Log.writeln(" -- blockNum=", blockNum_); } }