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
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index cb98805..5d36195 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -339,22 +339,24 @@
   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 6e491b0..07c1611 100644
--- a/libartbase/base/bit_memory_region.h
+++ b/libartbase/base/bit_memory_region.h
@@ -57,6 +57,15 @@
     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 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 @@
 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 @@
     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 418d7c4..b0fc4d1 100644
--- a/libartbase/base/bit_table.h
+++ b/libartbase/base/bit_table.h
@@ -355,7 +355,7 @@
     // 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 @@
     // 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 a694148..2fd9052 100644
--- a/libartbase/base/bit_table_test.cc
+++ b/libartbase/base/bit_table_test.cc
@@ -34,7 +34,7 @@
       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 @@
   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 @@
   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 @@
     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 @@
   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 @@
   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 02fad46..6c3cc20 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@
 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 42d2478..a3c6e05 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -32,15 +32,12 @@
 }
 
 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 @@
   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 @@
 
 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 @@
                     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 cb43ced..ad52f37 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -289,13 +289,13 @@
   }
 
   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 @@
   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 @@
 
   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 @@
   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