package gc;
import util.ReferenceIterator;
import util.ReferenceList;
public class BitMap {
public static final byte WHITE = 3;
public static final byte GREY = 1;
public static final byte BLACK = 2;
public static final byte HATCHED = 0;
private int blockSize;
// In int/words
private int startAdr;
// In int/words
private int heapSize;
// In int/words
private int bitMapSize;
private byte[] bitMap;
public BitMap(int blockSize, int startAdr, int heapSize) {
this.blockSize = blockSize;
this.startAdr = startAdr;
if (heapSize > 64000)
{
heapSize = 64000;
}
this.heapSize = heapSize;
bitMapSize = ((heapSize / blockSize) / 4) + 1;
bitMap = new byte[bitMapSize];
}
public void clear() {
for (int i = 0; i < bitMap.length; i++) {
bitMap[i] = 0;
}
}
public boolean isRefWhite(int ref) {
int index = getIndex(ref);
int offSet = getOffset(ref);
if (((bitMap[index] & (1 << (offSet << 1))) != 0) && ((bitMap[index] & (1 << ((offSet << 1) + 1))) != 0)) {
return true;
}
return false;
}
public boolean isRefGrey(int ref) {
int index = getIndex(ref);
int offSet = getOffset(ref);
if (((bitMap[index] & (1 << (offSet << 1))) != 0) && ((bitMap[index] & (1 << ((offSet << 1) + 1))) == 0)) {
return true;
}
return false;
}
public boolean isRefBlack(int ref) {
int index = getIndex(ref);
int offSet = getOffset(ref);
if (((bitMap[index] & (1 << (offSet << 1))) == 0) && ((bitMap[index] & (1 << ((offSet << 1) + 1))) != 0)) {
return true;
}
return false;
}
public boolean isRefHatched(int ref) {
int index = getIndex(ref);
int offSet = getOffset(ref);
if (((bitMap[index] & (1 << (offSet << 1))) == 0) && ((bitMap[index] & (1 << ((offSet << 1) + 1))) == 0)) {
return true;
}
return false;
}
public void shadeRefGrey(int ref) {
int index = getIndex(ref);
int offSet = getOffset(ref);
bitMap[index] = (byte) (bitMap[index] | (1 << (offSet << 1)));
bitMap[index] = (byte) (bitMap[index] & ~(1 << ((offSet << 1) + 1)));
}
private int getOffset(int ref) {
return ((ref - startAdr) / blockSize) & 0x3;
}
private int getIndex(int ref) {
return ((ref - startAdr) / blockSize) >> 2;
}
public void shadeRefWhite(int ref) {
int index = getIndex(ref);
int offSet = getOffset(ref);
bitMap[index] = (byte) (bitMap[index] | (1 << (offSet << 1)));
bitMap[index] = (byte) (bitMap[index] | (1 << ((offSet << 1) + 1)));
}
public void shadeRefBlack(int ref) {
int index = getIndex(ref);
int offSet = getOffset(ref);
bitMap[index] = (byte) (bitMap[index] & (~(1 << (offSet << 1))));
bitMap[index] = (byte) (bitMap[index] | (1 << ((offSet << 1) + 1)));
}
public ReferenceIterator getFreeList() {
ReferenceList freeList = new ReferenceList();
int i = 0;
while (i < bitMap.length) {
byte nextByte = bitMap[i];
if (nextByte != 0) {
int ref = ((i << 2) * blockSize) + startAdr;
for (int j = 0; j < 4; j++) {
if (isRefWhite(ref))
{
freeList.add(ref);
shadeRefHatched(ref);
}
else if (isRefBlack(ref))
{
shadeRefWhite(ref);
}
ref += blockSize;
}
}
i++;
}
return freeList.iterator();
}
private void shadeRefHatched(int ref) {
int index = getIndex(ref);
int offSet = getOffset(ref);
bitMap[index] = (byte) (bitMap[index] & ~(1 << (offSet << 1)));
bitMap[index] = (byte) (bitMap[index] & ~(1 << ((offSet << 1) + 1)));
}
public boolean isWithinRangeOfHeap(int possibleRef) {
return (possibleRef >= startAdr) && (possibleRef < startAdr + heapSize);
}
public int getSize() {
return this.bitMapSize;
}
}