diff options
author | 2018-08-03 14:52:32 +0100 | |
---|---|---|
committer | 2018-08-10 12:40:01 +0100 | |
commit | 0c3aa31b7151c3b67aa0dff1ae2b8718eeb905c7 (patch) | |
tree | b7153d8f452ba686cc88052079aafae3f838d34e | |
parent | 971a80e5aa36955d9fee6b479a5cbd554f50ca08 (diff) |
Move varint encoding/decoding to BitMemoryReader/Writer.
Test: test-art-host-gtest-bit_memory_region_test
Change-Id: I0f7d7dfc9efe9df0e3e746b1741c46f06a0bd3b4
-rw-r--r-- | compiler/optimizing/stack_map_stream.cc | 8 | ||||
-rw-r--r-- | libartbase/base/bit_memory_region.h | 27 | ||||
-rw-r--r-- | libartbase/base/bit_memory_region_test.cc | 18 | ||||
-rw-r--r-- | libartbase/base/bit_table.h | 40 | ||||
-rw-r--r-- | libartbase/base/bit_table_test.cc | 16 | ||||
-rw-r--r-- | runtime/stack_map.cc | 20 | ||||
-rw-r--r-- | runtime/stack_map.h | 6 |
7 files changed, 68 insertions, 67 deletions
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc index 3918b65a62..60ca61c133 100644 --- a/compiler/optimizing/stack_map_stream.cc +++ b/compiler/optimizing/stack_map_stream.cc @@ -296,10 +296,10 @@ ScopedArenaVector<uint8_t> StackMapStream::Encode() { 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 f9b643e2c2..bcdc57346d 100644 --- a/libartbase/base/bit_memory_region.h +++ b/libartbase/base/bit_memory_region.h @@ -202,6 +202,9 @@ class BitMemoryRegion FINAL : public ValueObject { 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 @@ class BitMemoryReader { 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 @@ class BitMemoryWriter { 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 b7546985a9..02623bf040 100644 --- a/libartbase/base/bit_memory_region_test.cc +++ b/libartbase/base/bit_memory_region_test.cc @@ -33,6 +33,24 @@ static void CheckBits(uint8_t* data, } } +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 18de3d33d3..7fec51e45f 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 @@ class BitTableBase { 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 @@ class BitTableBuilderBase { 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 @@ class BitmapTableBuilder { 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 4f25730152..bf32dc6e00 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 b0c59a67dd..689904a983 100644 --- a/runtime/stack_map.cc +++ b/runtime/stack_map.cc @@ -36,7 +36,7 @@ ALWAYS_INLINE static void DecodeTable(BitTable<Accessor>& table, 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 @@ ALWAYS_INLINE static void DecodeTable(BitTable<Accessor>& table, 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 @@ ALWAYS_INLINE void CodeInfo::Deduper::DedupeTable(BitMemoryReader& reader) { } 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 @@ size_t CodeInfo::Deduper::Dedupe(const uint8_t* code_info) { 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 cde08f312b..bfd646d599 100644 --- a/runtime/stack_map.h +++ b/runtime/stack_map.h @@ -436,9 +436,9 @@ class CodeInfo { 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: |