| /* |
| * 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_); |
| } |
| } |
| |
| |