blob: 292037f7874e6b94ce26ad9ee37f3561ce8e33ba [file] [log] [blame]
/*
* Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.utilities;
import sun.jvm.hotspot.debugger.*;
/** Manages a bitmap of the specified bit size */
public class BitMap {
public BitMap(int sizeInBits) {
this.size = sizeInBits;
int nofWords = sizeInWords();
data = new int[nofWords];
}
public int size() {
return size;
}
// Accessors
public boolean at(int offset) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(offset>=0 && offset < size(), "BitMap index out of bounds");
}
return Bits.isSetNthBit(wordFor(offset), offset % bitsPerWord);
}
public void atPut(int offset, boolean value) {
int index = indexFor(offset);
int pos = offset % bitsPerWord;
if (value) {
data[index] = Bits.setNthBit(data[index], pos);
} else {
data[index] = Bits.clearNthBit(data[index], pos);
}
}
public void set_size(int value) {
size = value;
}
public void set_map(Address addr) {
for (int i=0; i<sizeInWords(); i++) {
data[i] = (int) addr.getCIntegerAt(0, bytesPerWord, true);
addr = addr.addOffsetTo(bytesPerWord);
}
}
public void clear() {
for (int i = 0; i < sizeInWords(); i++) {
data[i] = Bits.NoBits;
}
}
public void iterate(BitMapClosure blk) {
for (int index = 0; index < sizeInWords(); index++) {
int rest = data[index];
for (int offset = index * bitsPerWord; rest != Bits.NoBits; offset++) {
if (rest % 2 == 1) {
if (offset < size()) {
blk.doBit(offset);
} else {
return; // Passed end of map
}
}
rest = rest >>> 1;
}
}
}
/** Sets this bitmap to the logical union of it and the
argument. Both bitmaps must be the same size. Returns true if a
change was caused in this bitmap. */
public boolean setUnion(BitMap other) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(size() == other.size(), "must have same size");
}
boolean changed = false;
for (int index = 0; index < sizeInWords(); index++) {
int temp = data[index] | other.data[index];
changed = changed || (temp != data[index]);
data[index] = temp;
}
return changed;
}
/** Sets this bitmap to the logical intersection of it and the
argument. Both bitmaps must be the same size. */
public void setIntersection(BitMap other) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(size() == other.size(), "must have same size");
}
for (int index = 0; index < sizeInWords(); index++) {
data[index] = data[index] & (other.data[index]);
}
}
/** Sets this bitmap to the contents of the argument. Both bitmaps
must be the same size. */
public void setFrom(BitMap other) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(size() == other.size(), "must have same size");
}
for (int index = 0; index < sizeInWords(); index++) {
data[index] = other.data[index];
}
}
/** Sets this bitmap to the logical difference between it and the
argument; that is, any bits that are set in the argument are
cleared in this bitmap. Both bitmaps must be the same size.
Returns true if a change was caused in this bitmap. */
public boolean setDifference(BitMap other) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(size() == other.size(), "must have same size");
}
boolean changed = false;
for (int index = 0; index < sizeInWords(); index++) {
int temp = data[index] & ~(other.data[index]);
changed = changed || (temp != data[index]);
data[index] = temp;
}
return changed;
}
/** Both bitmaps must be the same size. */
public boolean isSame(BitMap other) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(size() == other.size(), "must have same size");
}
for (int index = 0; index < sizeInWords(); index++) {
if (data[index] != (other.data[index])) return false;
}
return true;
}
public int getNextOneOffset(int l_offset, int r_offset) {
if (l_offset == r_offset) {
return l_offset;
}
int index = indexFor(l_offset);
int r_index = indexFor(r_offset);
int res_offset = l_offset;
int pos = bitInWord(res_offset);
int res = data[index] >> pos;
if (res != 0) {
// find the position of the 1-bit
for (; (res & 1) == 0; res_offset++) {
res = res >> 1;
}
return res_offset;
}
// skip over all word length 0-bit runs
for (index++; index < r_index; index++) {
res = data[index];
if (res != 0) {
// found a 1, return the offset
for (res_offset = index * bitsPerWord; (res & 1) == 0; res_offset++) {
res = res >> 1;
}
return res_offset;
}
}
return r_offset;
}
//----------------------------------------------------------------------
// Internals only below this point
//
private int size; // in bits
private int[] data;
private static final int bitsPerWord = 32;
private static final int bytesPerWord = 4;
private int sizeInWords() {
return (size() + bitsPerWord - 1) / bitsPerWord;
}
private int indexFor(int offset) {
return offset / bitsPerWord;
}
private int wordFor(int offset) {
return data[offset / bitsPerWord];
}
private int bitInWord(int offset) {
return offset & (bitsPerWord - 1);
}
}