Provide BitField64 utility class.

R=svenpanne@chromium.org
TEST=cctest/test-conversions/BitField64

Review URL: https://codereview.chromium.org/14643004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14681 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2013-05-15 12:29:13 +00:00
parent a025371c4a
commit 3d5b800943
2 changed files with 46 additions and 19 deletions

View File

@ -242,42 +242,52 @@ inline int StrLength(const char* string) {
// ----------------------------------------------------------------------------
// BitField is a help template for encoding and decode bitfield with
// unsigned content.
template<class T, int shift, int size>
class BitField {
template<class T, int shift, int size, class U>
class BitFieldBase {
public:
// A uint32_t mask of bit field. To use all bits of a uint32 in a
// bitfield without compiler warnings we have to compute 2^32 without
// using a shift count of 32.
static const uint32_t kMask = ((1U << shift) << size) - (1U << shift);
static const uint32_t kShift = shift;
static const uint32_t kSize = size;
// A type U mask of bit field. To use all bits of a type U of x bits
// in a bitfield without compiler warnings we have to compute 2^x
// without using a shift count of x in the computation.
static const U kOne = static_cast<U>(1U);
static const U kMask = ((kOne << shift) << size) - (kOne << shift);
static const U kShift = shift;
static const U kSize = size;
// Value for the field with all bits set.
static const T kMax = static_cast<T>((1U << size) - 1);
// Tells whether the provided value fits into the bit field.
static bool is_valid(T value) {
return (static_cast<uint32_t>(value) & ~static_cast<uint32_t>(kMax)) == 0;
return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
}
// Returns a uint32_t with the bit field value encoded.
static uint32_t encode(T value) {
// Returns a type U with the bit field value encoded.
static U encode(T value) {
ASSERT(is_valid(value));
return static_cast<uint32_t>(value) << shift;
return static_cast<U>(value) << shift;
}
// Returns a uint32_t with the bit field value updated.
static uint32_t update(uint32_t previous, T value) {
// Returns a type U with the bit field value updated.
static U update(U previous, T value) {
return (previous & ~kMask) | encode(value);
}
// Extracts the bit field from the value.
static T decode(uint32_t value) {
static T decode(U value) {
return static_cast<T>((value & kMask) >> shift);
}
};
template<class T, int shift, int size>
class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
template<class T, int shift, int size>
class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
// ----------------------------------------------------------------------------
// Hash function.

View File

@ -249,15 +249,13 @@ TEST(ExponentNumberStr) {
CHECK_EQ(1e-106, StringToDouble(&uc, ".000001e-100", NO_FLAGS));
}
class OneBit1: public BitField<uint32_t, 0, 1> {};
class OneBit2: public BitField<uint32_t, 7, 1> {};
class EightBit1: public BitField<uint32_t, 0, 8> {};
class EightBit2: public BitField<uint32_t, 13, 8> {};
TEST(BitField) {
uint32_t x;
// One bit bit field can hold values 0 and 1.
class OneBit1: public BitField<uint32_t, 0, 1> {};
class OneBit2: public BitField<uint32_t, 7, 1> {};
CHECK(!OneBit1::is_valid(static_cast<uint32_t>(-1)));
CHECK(!OneBit2::is_valid(static_cast<uint32_t>(-1)));
for (int i = 0; i < 2; i++) {
@ -273,6 +271,8 @@ TEST(BitField) {
CHECK(!OneBit2::is_valid(2));
// Eight bit bit field can hold values from 0 tp 255.
class EightBit1: public BitField<uint32_t, 0, 8> {};
class EightBit2: public BitField<uint32_t, 13, 8> {};
CHECK(!EightBit1::is_valid(static_cast<uint32_t>(-1)));
CHECK(!EightBit2::is_valid(static_cast<uint32_t>(-1)));
for (int i = 0; i < 256; i++) {
@ -286,3 +286,20 @@ TEST(BitField) {
CHECK(!EightBit1::is_valid(256));
CHECK(!EightBit2::is_valid(256));
}
TEST(BitField64) {
uint64_t x;
// Test most significant bits.
class UpperBits: public BitField64<int, 61, 3> {};
x = V8_2PART_UINT64_C(0xE0000000, 00000000);
CHECK(x == UpperBits::encode(7));
CHECK_EQ(7, UpperBits::decode(x));
// Test the 32/64-bit boundary bits.
class MiddleBits: public BitField64<int, 31, 2> {};
x = V8_2PART_UINT64_C(0x00000001, 80000000);
CHECK(x == MiddleBits::encode(3));
CHECK_EQ(3, MiddleBits::decode(x));
}