Provide BitField64 utility class.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 15 May 2013 12:29:13 +0000 (12:29 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 15 May 2013 12:29:13 +0000 (12:29 +0000)
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

src/utils.h
test/cctest/test-conversions.cc

index b2c2ff1..90d7f3c 100644 (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.
 
index 651dc59..398e832 100644 (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));
+}