Move varint encoding/decoding to BitMemoryReader/Writer.
Test: test-art-host-gtest-bit_memory_region_test
Change-Id: I0f7d7dfc9efe9df0e3e746b1741c46f06a0bd3b4
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index 3918b65..60ca61c 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -296,10 +296,10 @@
ScopedArenaVector<uint8_t> buffer(allocator_->Adapter(kArenaAllocStackMapStream));
BitMemoryWriter<ScopedArenaVector<uint8_t>> out(&buffer);
- EncodeVarintBits(out, packed_frame_size_);
- EncodeVarintBits(out, core_spill_mask_);
- EncodeVarintBits(out, fp_spill_mask_);
- EncodeVarintBits(out, num_dex_registers_);
+ out.WriteVarint(packed_frame_size_);
+ out.WriteVarint(core_spill_mask_);
+ out.WriteVarint(fp_spill_mask_);
+ out.WriteVarint(num_dex_registers_);
EncodeTable(out, stack_maps_);
EncodeTable(out, register_masks_);
EncodeTable(out, stack_masks_);
diff --git a/libartbase/base/bit_memory_region.h b/libartbase/base/bit_memory_region.h
index f9b643e..bcdc573 100644
--- a/libartbase/base/bit_memory_region.h
+++ b/libartbase/base/bit_memory_region.h
@@ -202,6 +202,9 @@
size_t bit_size_ = 0;
};
+constexpr uint32_t kVarintHeaderBits = 4;
+constexpr uint32_t kVarintSmallValue = 11; // Maximum value which is stored as-is.
+
class BitMemoryReader {
public:
BitMemoryReader(BitMemoryReader&&) = default;
@@ -230,6 +233,18 @@
return ReadRegion(/* bit_length */ 1).LoadBit(/* bit_offset */ 0);
}
+ // Read variable-length bit-packed integer.
+ // The first four bits determine the variable length of the encoded integer:
+ // Values 0..11 represent the result as-is, with no further following bits.
+ // Values 12..15 mean the result is in the next 8/16/24/32-bits respectively.
+ ALWAYS_INLINE uint32_t ReadVarint() {
+ uint32_t x = ReadBits(kVarintHeaderBits);
+ if (x > kVarintSmallValue) {
+ x = ReadBits((x - kVarintSmallValue) * kBitsPerByte);
+ }
+ return x;
+ }
+
private:
// Represents all of the bits which were read so far. There is no upper bound.
// Therefore, by definition, the "cursor" is always at the end of the region.
@@ -274,6 +289,18 @@
Allocate(1).StoreBit(/* bit_offset */ 0, value);
}
+ // Write variable-length bit-packed integer.
+ ALWAYS_INLINE void WriteVarint(uint32_t value) {
+ if (value <= kVarintSmallValue) {
+ WriteBits(value, kVarintHeaderBits);
+ } else {
+ uint32_t num_bits = RoundUp(MinimumBitsToStore(value), kBitsPerByte);
+ uint32_t header = kVarintSmallValue + num_bits / kBitsPerByte;
+ WriteBits(header, kVarintHeaderBits);
+ WriteBits(value, num_bits);
+ }
+ }
+
ALWAYS_INLINE void ByteAlign() {
size_t end = bit_start_ + bit_offset_;
bit_offset_ += RoundUp(end, kBitsPerByte) - end;
diff --git a/libartbase/base/bit_memory_region_test.cc b/libartbase/base/bit_memory_region_test.cc
index b754698..02623bf 100644
--- a/libartbase/base/bit_memory_region_test.cc
+++ b/libartbase/base/bit_memory_region_test.cc
@@ -33,6 +33,24 @@
}
}
+TEST(BitMemoryRegion, TestVarint) {
+ for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
+ uint32_t values[] = { 0, 1, 11, 12, 15, 16, 255, 256, 1u << 16, 1u << 24, ~1u, ~0u };
+ for (uint32_t value : values) {
+ std::vector<uint8_t> buffer;
+ BitMemoryWriter<std::vector<uint8_t>> writer(&buffer, start_bit_offset);
+ writer.WriteVarint(value);
+
+ BitMemoryReader reader(buffer.data(), start_bit_offset);
+ uint32_t result = reader.ReadVarint();
+ uint32_t upper_bound = RoundUp(MinimumBitsToStore(value), kBitsPerByte) + kVarintHeaderBits;
+ EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
+ EXPECT_EQ(value, result);
+ EXPECT_GE(upper_bound, writer.NumberOfWrittenBits());
+ }
+ }
+}
+
TEST(BitMemoryRegion, TestBit) {
uint8_t data[sizeof(uint32_t) * 2];
for (size_t bit_offset = 0; bit_offset < 2 * sizeof(uint32_t) * kBitsPerByte; ++bit_offset) {
diff --git a/libartbase/base/bit_table.h b/libartbase/base/bit_table.h
index 18de3d3..7fec51e 100644
--- a/libartbase/base/bit_table.h
+++ b/libartbase/base/bit_table.h
@@ -33,34 +33,6 @@
namespace art {
-constexpr uint32_t kVarintHeaderBits = 4;
-constexpr uint32_t kVarintSmallValue = 11; // Maximum value which is stored as-is.
-
-// Load variable-length bit-packed integer from `data` starting at `bit_offset`.
-// The first four bits determine the variable length of the encoded integer:
-// Values 0..11 represent the result as-is, with no further following bits.
-// Values 12..15 mean the result is in the next 8/16/24/32-bits respectively.
-ALWAYS_INLINE static inline uint32_t DecodeVarintBits(BitMemoryReader& reader) {
- uint32_t x = reader.ReadBits(kVarintHeaderBits);
- if (x > kVarintSmallValue) {
- x = reader.ReadBits((x - kVarintSmallValue) * kBitsPerByte);
- }
- return x;
-}
-
-// Store variable-length bit-packed integer from `data` starting at `bit_offset`.
-template<typename Vector>
-ALWAYS_INLINE static inline void EncodeVarintBits(BitMemoryWriter<Vector>& out, uint32_t value) {
- if (value <= kVarintSmallValue) {
- out.WriteBits(value, kVarintHeaderBits);
- } else {
- uint32_t num_bits = RoundUp(MinimumBitsToStore(value), kBitsPerByte);
- uint32_t header = kVarintSmallValue + num_bits / kBitsPerByte;
- out.WriteBits(header, kVarintHeaderBits);
- out.WriteBits(value, num_bits);
- }
-}
-
// Generic purpose table of uint32_t values, which are tightly packed at bit level.
// It has its own header with the number of rows and the bit-widths of all columns.
// The values are accessible by (row, column). The value -1 is stored efficiently.
@@ -78,11 +50,11 @@
ALWAYS_INLINE void Decode(BitMemoryReader& reader) {
// Decode row count and column sizes from the table header.
size_t initial_bit_offset = reader.NumberOfReadBits();
- num_rows_ = DecodeVarintBits(reader);
+ num_rows_ = reader.ReadVarint();
if (num_rows_ != 0) {
column_offset_[0] = 0;
for (uint32_t i = 0; i < kNumColumns; i++) {
- size_t column_end = column_offset_[i] + DecodeVarintBits(reader);
+ size_t column_end = column_offset_[i] + reader.ReadVarint();
column_offset_[i + 1] = dchecked_integral_cast<uint16_t>(column_end);
}
}
@@ -386,11 +358,11 @@
std::array<uint32_t, kNumColumns> column_bits;
Measure(&column_bits);
- EncodeVarintBits(out, size());
+ out.WriteVarint(size());
if (size() != 0) {
// Write table header.
for (uint32_t c = 0; c < kNumColumns; c++) {
- EncodeVarintBits(out, column_bits[c]);
+ out.WriteVarint(column_bits[c]);
}
// Write table data.
@@ -475,9 +447,9 @@
void Encode(BitMemoryWriter<Vector>& out) const {
size_t initial_bit_offset = out.NumberOfWrittenBits();
- EncodeVarintBits(out, size());
+ out.WriteVarint(size());
if (size() != 0) {
- EncodeVarintBits(out, max_num_bits_);
+ out.WriteVarint(max_num_bits_);
// Write table data.
for (MemoryRegion row : rows_) {
diff --git a/libartbase/base/bit_table_test.cc b/libartbase/base/bit_table_test.cc
index 4f25730..bf32dc6 100644
--- a/libartbase/base/bit_table_test.cc
+++ b/libartbase/base/bit_table_test.cc
@@ -26,22 +26,6 @@
namespace art {
-TEST(BitTableTest, TestVarint) {
- for (size_t start_bit_offset = 0; start_bit_offset <= 32; start_bit_offset++) {
- uint32_t values[] = { 0, 1, 11, 12, 15, 16, 255, 256, ~1u, ~0u };
- for (uint32_t value : values) {
- std::vector<uint8_t> buffer;
- BitMemoryWriter<std::vector<uint8_t>> writer(&buffer, start_bit_offset);
- EncodeVarintBits(writer, value);
-
- BitMemoryReader reader(buffer.data(), start_bit_offset);
- uint32_t result = DecodeVarintBits(reader);
- EXPECT_EQ(writer.NumberOfWrittenBits(), reader.NumberOfReadBits());
- EXPECT_EQ(value, result);
- }
- }
-}
-
TEST(BitTableTest, TestEmptyTable) {
MallocArenaPool pool;
ArenaStack arena_stack(&pool);
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index b0c59a6..689904a 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -36,7 +36,7 @@
BitMemoryReader& reader,
const uint8_t* reader_data) {
if (reader.ReadBit() /* is_deduped */) {
- ssize_t bit_offset = reader.NumberOfReadBits() - DecodeVarintBits(reader);
+ ssize_t bit_offset = reader.NumberOfReadBits() - reader.ReadVarint();
BitMemoryReader reader2(reader_data, bit_offset); // The offset is negative.
table.Decode(reader2);
} else {
@@ -46,10 +46,10 @@
void CodeInfo::Decode(const uint8_t* data, DecodeFlags flags) {
BitMemoryReader reader(data);
- packed_frame_size_ = DecodeVarintBits(reader);
- core_spill_mask_ = DecodeVarintBits(reader);
- fp_spill_mask_ = DecodeVarintBits(reader);
- number_of_dex_registers_ = DecodeVarintBits(reader);
+ packed_frame_size_ = reader.ReadVarint();
+ core_spill_mask_ = reader.ReadVarint();
+ fp_spill_mask_ = reader.ReadVarint();
+ number_of_dex_registers_ = reader.ReadVarint();
DecodeTable(stack_maps_, reader, data);
DecodeTable(register_masks_, reader, data);
DecodeTable(stack_masks_, reader, data);
@@ -82,7 +82,7 @@
} else {
writer_.WriteBit(true); // Is deduped.
size_t bit_offset = writer_.NumberOfWrittenBits();
- EncodeVarintBits(writer_, bit_offset - it.first->second);
+ writer_.WriteVarint(bit_offset - it.first->second);
}
}
@@ -90,10 +90,10 @@
writer_.ByteAlign();
size_t deduped_offset = writer_.NumberOfWrittenBits() / kBitsPerByte;
BitMemoryReader reader(code_info);
- EncodeVarintBits(writer_, DecodeVarintBits(reader)); // packed_frame_size_.
- EncodeVarintBits(writer_, DecodeVarintBits(reader)); // core_spill_mask_.
- EncodeVarintBits(writer_, DecodeVarintBits(reader)); // fp_spill_mask_.
- EncodeVarintBits(writer_, DecodeVarintBits(reader)); // number_of_dex_registers_.
+ writer_.WriteVarint(reader.ReadVarint()); // packed_frame_size_.
+ writer_.WriteVarint(reader.ReadVarint()); // core_spill_mask_.
+ writer_.WriteVarint(reader.ReadVarint()); // fp_spill_mask_.
+ writer_.WriteVarint(reader.ReadVarint()); // number_of_dex_registers_.
DedupeTable<StackMap>(reader);
DedupeTable<RegisterMask>(reader);
DedupeTable<MaskInfo>(reader);
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index cde08f3..bfd646d 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -436,9 +436,9 @@
ALWAYS_INLINE static QuickMethodFrameInfo DecodeFrameInfo(const uint8_t* data) {
BitMemoryReader reader(data);
return QuickMethodFrameInfo(
- DecodeVarintBits(reader) * kStackAlignment, // Decode packed_frame_size_ and unpack.
- DecodeVarintBits(reader), // core_spill_mask_.
- DecodeVarintBits(reader)); // fp_spill_mask_.
+ reader.ReadVarint() * kStackAlignment, // Decode packed_frame_size_ and unpack.
+ reader.ReadVarint(), // core_spill_mask_.
+ reader.ReadVarint()); // fp_spill_mask_.
}
private: