diff options
author | 2018-06-26 18:13:49 +0100 | |
---|---|---|
committer | 2018-06-27 10:15:32 +0100 | |
commit | a38e6cf2aaf4fd3d92b05c0a7a146fb5525ea72d (patch) | |
tree | 377c74c834776b9942bb7c2853e44447dac27f83 | |
parent | f6ba5b316b51d0fb9f91cb51a42e51dfeee62ee4 (diff) |
Remove explicit size from CodeInfo.
It was mostly there since it was necessary to create the
bound-checked MemoryRegion for loading.
The new BitMemoryReader interface is much easier to
tweak to avoid needing to know the size ahead of time.
Keep the CHECK that the loader reads the expected number
of bytes, but move it to FillInCodeInfo.
This saves 0.2% of .oat file size.
Test: test-art-host-gtest-stack_map_test
Test: test-art-host-gtest-bit_table_test
Change-Id: I92ee936e9fd004da61b90841aff9c9f2029fcfbf
-rw-r--r-- | compiler/optimizing/stack_map_stream.cc | 14 | ||||
-rw-r--r-- | libartbase/base/bit_memory_region.h | 41 | ||||
-rw-r--r-- | libartbase/base/bit_table.h | 4 | ||||
-rw-r--r-- | libartbase/base/bit_table_test.cc | 12 | ||||
-rw-r--r-- | runtime/oat.h | 4 | ||||
-rw-r--r-- | runtime/stack_map.cc | 14 | ||||
-rw-r--r-- | runtime/stack_map.h | 7 |
7 files changed, 51 insertions, 45 deletions
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc index cb988050ff..5d361953ba 100644 --- a/compiler/optimizing/stack_map_stream.cc +++ b/compiler/optimizing/stack_map_stream.cc @@ -339,22 +339,24 @@ size_t StackMapStream::PrepareForFillIn() { dex_register_maps_.Encode(out); dex_register_catalog_.Encode(out); - return UnsignedLeb128Size(out_.size()) + out_.size(); + return out_.size(); } void StackMapStream::FillInCodeInfo(MemoryRegion region) { DCHECK(in_stack_map_ == false) << "Mismatched Begin/End calls"; DCHECK(in_inline_info_ == false) << "Mismatched Begin/End calls"; DCHECK_NE(0u, out_.size()) << "PrepareForFillIn not called before FillIn"; - DCHECK_EQ(region.size(), UnsignedLeb128Size(out_.size()) + out_.size()); + DCHECK_EQ(region.size(), out_.size()); - uint8_t* ptr = EncodeUnsignedLeb128(region.begin(), out_.size()); - region.CopyFromVector(ptr - region.begin(), out_); + region.CopyFromVector(0, out_); + + // Verify that we can load the CodeInfo and check some essentials. + CodeInfo code_info(region); + CHECK_EQ(code_info.Size(), out_.size()); + CHECK_EQ(code_info.GetNumberOfStackMaps(), stack_maps_.size()); // Verify all written data (usually only in debug builds). if (kVerifyStackMaps) { - CodeInfo code_info(region); - CHECK_EQ(code_info.GetNumberOfStackMaps(), stack_maps_.size()); for (const auto& dcheck : dchecks_) { dcheck(code_info); } diff --git a/libartbase/base/bit_memory_region.h b/libartbase/base/bit_memory_region.h index 6e491b0868..07c1611c60 100644 --- a/libartbase/base/bit_memory_region.h +++ b/libartbase/base/bit_memory_region.h @@ -57,6 +57,15 @@ class BitMemoryRegion FINAL : public ValueObject { return result; } + // Increase the size of the region and return the newly added range (starting at the old end). + ALWAYS_INLINE BitMemoryRegion Extend(size_t bit_length) { + BitMemoryRegion result = *this; + result.bit_start_ += result.bit_size_; + result.bit_size_ = bit_length; + bit_size_ += bit_length; + return result; + } + // Load a single bit in the region. The bit at offset 0 is the least // significant bit in the first byte. ATTRIBUTE_NO_SANITIZE_ADDRESS // We might touch extra bytes due to the alignment. @@ -167,26 +176,26 @@ class BitMemoryRegion FINAL : public ValueObject { class BitMemoryReader { public: - explicit BitMemoryReader(BitMemoryRegion region, size_t bit_offset = 0) - : region_(region), bit_offset_(bit_offset) { } + explicit BitMemoryReader(const uint8_t* data, size_t bit_offset = 0) { + MemoryRegion region(const_cast<uint8_t*>(data), BitsToBytesRoundUp(bit_offset)); + finished_region_ = BitMemoryRegion(region, 0, bit_offset); + DCHECK_EQ(GetBitOffset(), bit_offset); + } - size_t GetBitOffset() const { return bit_offset_; } + size_t GetBitOffset() const { return finished_region_.size_in_bits(); } ALWAYS_INLINE BitMemoryRegion Skip(size_t bit_length) { - BitMemoryRegion result = region_.Subregion(bit_offset_, bit_length); - bit_offset_ += bit_length; - return result; + return finished_region_.Extend(bit_length); } ALWAYS_INLINE uint32_t ReadBits(size_t bit_length) { - uint32_t result = region_.LoadBits(bit_offset_, bit_length); - bit_offset_ += bit_length; - return result; + return finished_region_.Extend(bit_length).LoadBits(0, bit_length); } private: - BitMemoryRegion region_; - size_t bit_offset_; + // 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. + BitMemoryRegion finished_region_; DISALLOW_COPY_AND_ASSIGN(BitMemoryReader); }; @@ -195,7 +204,11 @@ template<typename Vector> class BitMemoryWriter { public: explicit BitMemoryWriter(Vector* out, size_t bit_offset = 0) - : out_(out), bit_offset_(bit_offset) { } + : out_(out), bit_offset_(bit_offset) { + DCHECK_EQ(GetBitOffset(), bit_offset); + } + + const uint8_t* data() const { return out_->data(); } size_t GetBitOffset() const { return bit_offset_; } @@ -210,10 +223,6 @@ class BitMemoryWriter { Allocate(bit_length).StoreBits(0, value, bit_length); } - BitMemoryRegion GetWrittenRegion() const { - return BitMemoryRegion(MemoryRegion(out_->data(), out_->size()), 0, bit_offset_); - } - private: Vector* out_; size_t bit_offset_; diff --git a/libartbase/base/bit_table.h b/libartbase/base/bit_table.h index 418d7c4251..b0fc4d1d1b 100644 --- a/libartbase/base/bit_table.h +++ b/libartbase/base/bit_table.h @@ -355,7 +355,7 @@ class BitTableBuilderBase { // Verify the written data. if (kIsDebugBuild) { BitTableBase<kNumColumns> table; - BitMemoryReader reader(out.GetWrittenRegion(), initial_bit_offset); + BitMemoryReader reader(out.data(), initial_bit_offset); table.Decode(reader); DCHECK_EQ(size(), table.NumRows()); for (uint32_t c = 0; c < kNumColumns; c++) { @@ -441,7 +441,7 @@ class BitmapTableBuilder { // Verify the written data. if (kIsDebugBuild) { BitTableBase<1> table; - BitMemoryReader reader(out.GetWrittenRegion(), initial_bit_offset); + BitMemoryReader reader(out.data(), initial_bit_offset); table.Decode(reader); DCHECK_EQ(size(), table.NumRows()); DCHECK_EQ(max_num_bits_, table.NumColumnBits(0)); diff --git a/libartbase/base/bit_table_test.cc b/libartbase/base/bit_table_test.cc index a6941487b2..2fd9052516 100644 --- a/libartbase/base/bit_table_test.cc +++ b/libartbase/base/bit_table_test.cc @@ -34,7 +34,7 @@ TEST(BitTableTest, TestVarint) { BitMemoryWriter<std::vector<uint8_t>> writer(&buffer, start_bit_offset); EncodeVarintBits(writer, value); - BitMemoryReader reader(writer.GetWrittenRegion(), start_bit_offset); + BitMemoryReader reader(buffer.data(), start_bit_offset); uint32_t result = DecodeVarintBits(reader); EXPECT_EQ(writer.GetBitOffset(), reader.GetBitOffset()); EXPECT_EQ(value, result); @@ -52,7 +52,7 @@ TEST(BitTableTest, TestEmptyTable) { BitTableBuilderBase<1> builder(&allocator); builder.Encode(writer); - BitMemoryReader reader(writer.GetWrittenRegion()); + BitMemoryReader reader(buffer.data()); BitTableBase<1> table(reader); EXPECT_EQ(writer.GetBitOffset(), reader.GetBitOffset()); EXPECT_EQ(0u, table.NumRows()); @@ -73,7 +73,7 @@ TEST(BitTableTest, TestSingleColumnTable) { builder.Add({kNoValue}); builder.Encode(writer); - BitMemoryReader reader(writer.GetWrittenRegion()); + BitMemoryReader reader(buffer.data()); BitTableBase<1> table(reader); EXPECT_EQ(writer.GetBitOffset(), reader.GetBitOffset()); EXPECT_EQ(4u, table.NumRows()); @@ -96,7 +96,7 @@ TEST(BitTableTest, TestUnalignedTable) { builder.Add({42u}); builder.Encode(writer); - BitMemoryReader reader(writer.GetWrittenRegion(), start_bit_offset); + BitMemoryReader reader(buffer.data(), start_bit_offset); BitTableBase<1> table(reader); EXPECT_EQ(writer.GetBitOffset(), reader.GetBitOffset()); EXPECT_EQ(1u, table.NumRows()); @@ -117,7 +117,7 @@ TEST(BitTableTest, TestBigTable) { builder.Add({62u, kNoValue, 63u, static_cast<uint32_t>(-3)}); builder.Encode(writer); - BitMemoryReader reader(writer.GetWrittenRegion()); + BitMemoryReader reader(buffer.data()); BitTableBase<4> table(reader); EXPECT_EQ(writer.GetBitOffset(), reader.GetBitOffset()); EXPECT_EQ(2u, table.NumRows()); @@ -167,7 +167,7 @@ TEST(BitTableTest, TestBitmapTable) { builder.Encode(writer); EXPECT_EQ(1 + static_cast<uint32_t>(POPCOUNT(value)), builder.size()); - BitMemoryReader reader(writer.GetWrittenRegion()); + BitMemoryReader reader(buffer.data()); BitTableBase<1> table(reader); EXPECT_EQ(writer.GetBitOffset(), reader.GetBitOffset()); for (auto it : indicies) { diff --git a/runtime/oat.h b/runtime/oat.h index 02fad46a0d..6c3cc20032 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,8 +32,8 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' }; - // Last oat version changed reason: Add method frame info to CodeInfo. - static constexpr uint8_t kOatVersion[] = { '1', '5', '0', '\0' }; + // Last oat version changed reason: Remove explicit size from CodeInfo. + static constexpr uint8_t kOatVersion[] = { '1', '5', '1', '\0' }; static constexpr const char* kImageLocationKey = "image-location"; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc index 42d24784de..a3c6e05045 100644 --- a/runtime/stack_map.cc +++ b/runtime/stack_map.cc @@ -32,15 +32,12 @@ CodeInfo::CodeInfo(const OatQuickMethodHeader* header) } void CodeInfo::Decode(const uint8_t* data) { - size_t non_header_size = DecodeUnsignedLeb128(&data); - size_ = UnsignedLeb128Size(non_header_size) + non_header_size; - const uint8_t* end = data + non_header_size; + const uint8_t* begin = data; frame_size_in_bytes_ = DecodeUnsignedLeb128(&data); core_spill_mask_ = DecodeUnsignedLeb128(&data); fp_spill_mask_ = DecodeUnsignedLeb128(&data); number_of_dex_registers_ = DecodeUnsignedLeb128(&data); - MemoryRegion region(const_cast<uint8_t*>(data), end - data); - BitMemoryReader reader(BitMemoryRegion(region), /* bit_offset */ 0); + BitMemoryReader reader(data, /* bit_offset */ 0); stack_maps_.Decode(reader); register_masks_.Decode(reader); stack_masks_.Decode(reader); @@ -49,7 +46,7 @@ void CodeInfo::Decode(const uint8_t* data) { dex_register_masks_.Decode(reader); dex_register_maps_.Decode(reader); dex_register_catalog_.Decode(reader); - CHECK_EQ(BitsToBytesRoundUp(reader.GetBitOffset()), region.size()) << "Invalid CodeInfo"; + size_in_bits_ = (data - begin) * kBitsPerByte + reader.GetBitOffset(); } BitTable<StackMap>::const_iterator CodeInfo::BinarySearchNativePc(uint32_t packed_pc) const { @@ -154,8 +151,7 @@ static void AddTableSizeStats(const char* table_name, void CodeInfo::AddSizeStats(/*out*/ Stats* parent) const { Stats* stats = parent->Child("CodeInfo"); - stats->AddBytes(size_); - stats->Child("Header")->AddBytes(UnsignedLeb128Size(size_)); + stats->AddBytes(Size()); AddTableSizeStats<StackMap>("StackMaps", stack_maps_, stats); AddTableSizeStats<RegisterMask>("RegisterMasks", register_masks_, stats); AddTableSizeStats<MaskInfo>("StackMasks", stack_masks_, stats); @@ -222,7 +218,7 @@ void CodeInfo::Dump(VariableIndentationOutputStream* vios, const MethodInfo& method_info) const { vios->Stream() << "CodeInfo" - << " BitSize=" << size_ * kBitsPerByte + << " BitSize=" << size_in_bits_ << "\n"; ScopedIndentation indent1(vios); DumpTable<StackMap>(vios, "StackMaps", stack_maps_, verbose); diff --git a/runtime/stack_map.h b/runtime/stack_map.h index cb43ced2a5..ad52f377cf 100644 --- a/runtime/stack_map.h +++ b/runtime/stack_map.h @@ -289,13 +289,13 @@ class CodeInfo { } explicit CodeInfo(MemoryRegion region) : CodeInfo(region.begin()) { - DCHECK_EQ(size_, region.size()); + DCHECK_EQ(Size(), region.size()); } explicit CodeInfo(const OatQuickMethodHeader* header); size_t Size() const { - return size_; + return BitsToBytesRoundUp(size_in_bits_); } bool HasInlineInfo() const { @@ -436,7 +436,6 @@ class CodeInfo { void AddSizeStats(/*out*/ Stats* parent) const; ALWAYS_INLINE static QuickMethodFrameInfo DecodeFrameInfo(const uint8_t* data) { - DecodeUnsignedLeb128(&data); return QuickMethodFrameInfo( DecodeUnsignedLeb128(&data), DecodeUnsignedLeb128(&data), @@ -455,7 +454,6 @@ class CodeInfo { void Decode(const uint8_t* data); - size_t size_; uint32_t frame_size_in_bytes_; uint32_t core_spill_mask_; uint32_t fp_spill_mask_; @@ -468,6 +466,7 @@ class CodeInfo { BitTable<MaskInfo> dex_register_masks_; BitTable<DexRegisterMapInfo> dex_register_maps_; BitTable<DexRegisterInfo> dex_register_catalog_; + uint32_t size_in_bits_; }; #undef ELEMENT_BYTE_OFFSET_AFTER |