Move MethodInfo to CodeInfo.

There is no need to treat it specially any more,
because of the de-duplication at BitTable level.

This saves 0.6% of oat file size.

Test: test-art-host-gtest
Change-Id: Ife7927d736243879a41d6f325d49ebf6930a63f6
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 0ed26d3..e6f3d0b 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -45,7 +45,7 @@
 namespace art {
 
 inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
-                                    const MethodInfo& method_info,
+                                    const CodeInfo& code_info,
                                     const BitTableRange<InlineInfo>& inline_infos)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   DCHECK(!outer_method->IsObsolete());
@@ -62,7 +62,7 @@
       return inline_info.GetArtMethod();
     }
 
-    uint32_t method_index = inline_info.GetMethodIndex(method_info);
+    uint32_t method_index = code_info.GetMethodIndexOf(inline_info);
     if (inline_info.GetDexPc() == static_cast<uint32_t>(-1)) {
       // "charAt" special case. It is the only non-leaf method we inline across dex files.
       ArtMethod* inlined_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt);
@@ -77,7 +77,7 @@
   for (InlineInfo inline_info : inline_infos) {
     DCHECK(!inline_info.EncodesArtMethod());
     DCHECK_NE(inline_info.GetDexPc(), static_cast<uint32_t>(-1));
-    uint32_t method_index = inline_info.GetMethodIndex(method_info);
+    uint32_t method_index = code_info.GetMethodIndexOf(inline_info);
     ArtMethod* inlined_method = class_linker->LookupResolvedMethod(method_index,
                                                                    method->GetDexCache(),
                                                                    method->GetClassLoader());
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index a5ebce5..5421f69 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -202,12 +202,11 @@
       DCHECK(current_code->IsOptimized());
       uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc);
       CodeInfo code_info(current_code, CodeInfo::DecodeFlags::InlineInfoOnly);
-      MethodInfo method_info = current_code->GetOptimizedMethodInfo();
       StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
       DCHECK(stack_map.IsValid());
       BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map);
       if (!inline_infos.empty()) {
-        caller = GetResolvedMethod(outer_method, method_info, inline_infos);
+        caller = GetResolvedMethod(outer_method, code_info, inline_infos);
       }
     }
     if (kIsDebugBuild && do_caller_check) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index be4e4e6..aca169b 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1236,7 +1236,6 @@
   CHECK(current_code->IsOptimized());
   uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc);
   CodeInfo code_info(current_code);
-  MethodInfo method_info = current_code->GetOptimizedMethodInfo();
   StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
   CHECK(stack_map.IsValid());
   uint32_t dex_pc = stack_map.GetDexPc();
@@ -1261,7 +1260,7 @@
       tag = "encoded ";
       caller = inline_info.GetArtMethod();
     } else {
-      uint32_t method_index = inline_info.GetMethodIndex(method_info);
+      uint32_t method_index = code_info.GetMethodIndexOf(inline_info);
       if (dex_pc == static_cast<uint32_t>(-1)) {
         tag = "special ";
         CHECK(inline_info.Equals(inline_infos.back()));
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 9aa0556..b92affa 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -411,7 +411,6 @@
 uint8_t* JitCodeCache::CommitCode(Thread* self,
                                   ArtMethod* method,
                                   uint8_t* stack_map,
-                                  uint8_t* method_info,
                                   uint8_t* roots_data,
                                   const uint8_t* code,
                                   size_t code_size,
@@ -423,7 +422,6 @@
   uint8_t* result = CommitCodeInternal(self,
                                        method,
                                        stack_map,
-                                       method_info,
                                        roots_data,
                                        code,
                                        code_size,
@@ -438,7 +436,6 @@
     result = CommitCodeInternal(self,
                                 method,
                                 stack_map,
-                                method_info,
                                 roots_data,
                                 code,
                                 code_size,
@@ -748,7 +745,6 @@
 uint8_t* JitCodeCache::CommitCodeInternal(Thread* self,
                                           ArtMethod* method,
                                           uint8_t* stack_map,
-                                          uint8_t* method_info,
                                           uint8_t* roots_data,
                                           const uint8_t* code,
                                           size_t code_size,
@@ -783,7 +779,6 @@
       method_header = OatQuickMethodHeader::FromCodePointer(code_ptr);
       new (method_header) OatQuickMethodHeader(
           (stack_map != nullptr) ? code_ptr - stack_map : 0u,
-          (method_info != nullptr) ? code_ptr - method_info : 0u,
           code_size);
       // Flush caches before we remove write permission because some ARMv8 Qualcomm kernels may
       // trigger a segfault if a page fault occurs when requesting a cache maintenance operation.
@@ -1046,14 +1041,12 @@
 
 size_t JitCodeCache::ReserveData(Thread* self,
                                  size_t stack_map_size,
-                                 size_t method_info_size,
                                  size_t number_of_roots,
                                  ArtMethod* method,
                                  uint8_t** stack_map_data,
-                                 uint8_t** method_info_data,
                                  uint8_t** roots_data) {
   size_t table_size = ComputeRootTableSize(number_of_roots);
-  size_t size = RoundUp(stack_map_size + method_info_size + table_size, sizeof(void*));
+  size_t size = RoundUp(stack_map_size + table_size, sizeof(void*));
   uint8_t* result = nullptr;
 
   {
@@ -1083,13 +1076,11 @@
   if (result != nullptr) {
     *roots_data = result;
     *stack_map_data = result + table_size;
-    *method_info_data = *stack_map_data + stack_map_size;
     FillRootTableLength(*roots_data, number_of_roots);
     return size;
   } else {
     *roots_data = nullptr;
     *stack_map_data = nullptr;
-    *method_info_data = nullptr;
     return 0;
   }
 }
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index d17fb26..29f9c9c 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -136,7 +136,6 @@
   uint8_t* CommitCode(Thread* self,
                       ArtMethod* method,
                       uint8_t* stack_map,
-                      uint8_t* method_info,
                       uint8_t* roots_data,
                       const uint8_t* code,
                       size_t code_size,
@@ -166,11 +165,9 @@
   // Return the number of bytes allocated.
   size_t ReserveData(Thread* self,
                      size_t stack_map_size,
-                     size_t method_info_size,
                      size_t number_of_roots,
                      ArtMethod* method,
                      uint8_t** stack_map_data,
-                     uint8_t** method_info_data,
                      uint8_t** roots_data)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!lock_);
@@ -295,7 +292,6 @@
   uint8_t* CommitCodeInternal(Thread* self,
                               ArtMethod* method,
                               uint8_t* stack_map,
-                              uint8_t* method_info,
                               uint8_t* roots_data,
                               const uint8_t* code,
                               size_t code_size,
diff --git a/runtime/method_info.h b/runtime/method_info.h
deleted file mode 100644
index 6f74678..0000000
--- a/runtime/method_info.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_METHOD_INFO_H_
-#define ART_RUNTIME_METHOD_INFO_H_
-
-#include <android-base/logging.h>
-
-#include "base/leb128.h"
-#include "base/macros.h"
-#include "base/bit_memory_region.h"
-
-namespace art {
-
-// Method info is for not dedupe friendly data of a method. Currently it only holds methods indices.
-// Putting this data in MethodInfo instead of code infos saves ~5% oat size.
-class MethodInfo {
-  using MethodIndexType = uint16_t;
-
- public:
-  // Reading mode
-  explicit MethodInfo(const uint8_t* ptr) {
-    if (ptr != nullptr) {
-      num_method_indices_ = DecodeUnsignedLeb128(&ptr);
-      region_ = BitMemoryRegion(
-          MemoryRegion(const_cast<uint8_t*>(ptr), num_method_indices_ * sizeof(MethodIndexType)));
-    }
-  }
-
-  // Writing mode
-  MethodInfo(uint8_t* ptr, size_t num_method_indices) : num_method_indices_(num_method_indices) {
-    DCHECK(ptr != nullptr);
-    ptr = EncodeUnsignedLeb128(ptr, num_method_indices_);
-    region_ = BitMemoryRegion(MemoryRegion(ptr, num_method_indices_ * sizeof(MethodIndexType)));
-  }
-
-  static size_t ComputeSize(size_t num_method_indices) {
-    uint8_t temp[8];
-    uint8_t* ptr = temp;
-    ptr = EncodeUnsignedLeb128(ptr, num_method_indices);
-    return (ptr - temp) + num_method_indices * sizeof(MethodIndexType);
-  }
-
-  ALWAYS_INLINE MethodIndexType GetMethodIndex(size_t index) const {
-    // Use bit functions to avoid pesky alignment requirements.
-    return region_.LoadBits(index * BitSizeOf<MethodIndexType>(), BitSizeOf<MethodIndexType>());
-  }
-
-  void SetMethodIndex(size_t index, MethodIndexType method_index) {
-    region_.StoreBits(index * BitSizeOf<MethodIndexType>(),
-                      method_index,
-                      BitSizeOf<MethodIndexType>());
-  }
-
-  size_t NumMethodIndices() const {
-    return num_method_indices_;
-  }
-
- private:
-  size_t num_method_indices_ = 0u;
-  BitMemoryRegion region_;
-};
-
-}  // namespace art
-
-#endif  // ART_RUNTIME_METHOD_INFO_H_
diff --git a/runtime/oat.h b/runtime/oat.h
index c286f46..69aaceb 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: Deduplicate stackmaps at BitTable level.
-  static constexpr uint8_t kOatVersion[] = { '1', '5', '7', '\0' };
+  // Last oat version changed reason: Move MethodInfo into CodeInfo.
+  static constexpr uint8_t kOatVersion[] = { '1', '5', '8', '\0' };
 
   static constexpr const char* kImageLocationKey = "image-location";
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/oat_quick_method_header.h b/runtime/oat_quick_method_header.h
index 3b9f466..8798c69 100644
--- a/runtime/oat_quick_method_header.h
+++ b/runtime/oat_quick_method_header.h
@@ -20,7 +20,6 @@
 #include "arch/instruction_set.h"
 #include "base/macros.h"
 #include "base/utils.h"
-#include "method_info.h"
 #include "quick/quick_method_frame_info.h"
 #include "stack_map.h"
 
@@ -33,10 +32,8 @@
  public:
   OatQuickMethodHeader() = default;
   OatQuickMethodHeader(uint32_t vmap_table_offset,
-                       uint32_t method_info_offset,
                        uint32_t code_size)
       : vmap_table_offset_(vmap_table_offset),
-        method_info_offset_(method_info_offset),
         code_size_(code_size) {
   }
 
@@ -74,20 +71,6 @@
     return code_ - vmap_table_offset_;
   }
 
-  const void* GetOptimizedMethodInfoPtr() const {
-    DCHECK(IsOptimized());
-    return reinterpret_cast<const void*>(code_ - method_info_offset_);
-  }
-
-  uint8_t* GetOptimizedMethodInfoPtr() {
-    DCHECK(IsOptimized());
-    return code_ - method_info_offset_;
-  }
-
-  MethodInfo GetOptimizedMethodInfo() const {
-    return MethodInfo(reinterpret_cast<const uint8_t*>(GetOptimizedMethodInfoPtr()));
-  }
-
   const uint8_t* GetCode() const {
     return code_;
   }
@@ -112,18 +95,6 @@
     return &vmap_table_offset_;
   }
 
-  uint32_t GetMethodInfoOffset() const {
-    return method_info_offset_;
-  }
-
-  void SetMethodInfoOffset(uint32_t offset) {
-    method_info_offset_ = offset;
-  }
-
-  const uint32_t* GetMethodInfoOffsetAddr() const {
-    return &method_info_offset_;
-  }
-
   const uint8_t* GetVmapTable() const {
     CHECK(!IsOptimized()) << "Unimplemented vmap table for optimizing compiler";
     return (vmap_table_offset_ == 0) ? nullptr : code_ - vmap_table_offset_;
@@ -186,11 +157,6 @@
 
   // The offset in bytes from the start of the vmap table to the end of the header.
   uint32_t vmap_table_offset_ = 0u;
-  // The offset in bytes from the start of the method info to the end of the header.
-  // The method info offset is not in the CodeInfo since CodeInfo has good dedupe properties that
-  // would be lost from doing so. The method info memory region contains method indices since they
-  // are hard to dedupe.
-  uint32_t method_info_offset_ = 0u;
   // The code size in bytes. The highest bit is used to signify if the compiled
   // code with the method header has should_deoptimize flag.
   uint32_t code_size_ = 0u;
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 85b1ea0..ce99fb9 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -81,9 +81,9 @@
   } else if (cur_quick_frame_ != nullptr) {
     if (IsInInlinedFrame()) {
       const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
-      MethodInfo method_info = method_header->GetOptimizedMethodInfo();
+      CodeInfo code_info(method_header);
       DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames);
-      return GetResolvedMethod(*GetCurrentQuickFrame(), method_info, current_inline_frames_);
+      return GetResolvedMethod(*GetCurrentQuickFrame(), code_info, current_inline_frames_);
     } else {
       return *cur_quick_frame_;
     }
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index e8746bc..cd82284 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -58,6 +58,7 @@
   BitMemoryReader reader(data, /* bit_offset */ 0);
   DecodeTable(stack_maps_, reader, data);
   DecodeTable(inline_infos_, reader, data);
+  DecodeTable(method_infos_, reader, data);
   if (flags & DecodeFlags::InlineInfoOnly) {
     return;
   }
@@ -99,6 +100,7 @@
   BitMemoryWriter<std::vector<uint8_t>> writer(out, /* bit_offset */ out->size() * kBitsPerByte);
   DedupeTable<StackMap>(writer, reader, dedupe_map);
   DedupeTable<InlineInfo>(writer, reader, dedupe_map);
+  DedupeTable<MethodInfo>(writer, reader, dedupe_map);
   DedupeTable<RegisterMask>(writer, reader, dedupe_map);
   DedupeTable<MaskInfo>(writer, reader, dedupe_map);
   DedupeTable<MaskInfo>(writer, reader, dedupe_map);
@@ -211,9 +213,10 @@
   Stats* stats = parent->Child("CodeInfo");
   stats->AddBytes(Size());
   AddTableSizeStats<StackMap>("StackMaps", stack_maps_, stats);
+  AddTableSizeStats<InlineInfo>("InlineInfos", inline_infos_, stats);
+  AddTableSizeStats<MethodInfo>("MethodInfo", method_infos_, stats);
   AddTableSizeStats<RegisterMask>("RegisterMasks", register_masks_, stats);
   AddTableSizeStats<MaskInfo>("StackMasks", stack_masks_, stats);
-  AddTableSizeStats<InlineInfo>("InlineInfos", inline_infos_, stats);
   AddTableSizeStats<MaskInfo>("DexRegisterMasks", dex_register_masks_, stats);
   AddTableSizeStats<DexRegisterMapInfo>("DexRegisterMaps", dex_register_maps_, stats);
   AddTableSizeStats<DexRegisterInfo>("DexRegisterCatalog", dex_register_catalog_, stats);
@@ -271,14 +274,14 @@
 void CodeInfo::Dump(VariableIndentationOutputStream* vios,
                     uint32_t code_offset,
                     bool verbose,
-                    InstructionSet instruction_set,
-                    const MethodInfo& method_info) const {
+                    InstructionSet instruction_set) const {
   vios->Stream() << "CodeInfo\n";
   ScopedIndentation indent1(vios);
   DumpTable<StackMap>(vios, "StackMaps", stack_maps_, verbose);
+  DumpTable<InlineInfo>(vios, "InlineInfos", inline_infos_, verbose);
+  DumpTable<MethodInfo>(vios, "MethodInfo", method_infos_, verbose);
   DumpTable<RegisterMask>(vios, "RegisterMasks", register_masks_, verbose);
   DumpTable<MaskInfo>(vios, "StackMasks", stack_masks_, verbose, true /* is_mask */);
-  DumpTable<InlineInfo>(vios, "InlineInfos", inline_infos_, verbose);
   DumpTable<MaskInfo>(vios, "DexRegisterMasks", dex_register_masks_, verbose, true /* is_mask */);
   DumpTable<DexRegisterMapInfo>(vios, "DexRegisterMaps", dex_register_maps_, verbose);
   DumpTable<DexRegisterInfo>(vios, "DexRegisterCatalog", dex_register_catalog_, verbose);
@@ -286,14 +289,13 @@
   // Display stack maps along with (live) Dex register maps.
   if (verbose) {
     for (StackMap stack_map : stack_maps_) {
-      stack_map.Dump(vios, *this, method_info, code_offset, instruction_set);
+      stack_map.Dump(vios, *this, code_offset, instruction_set);
     }
   }
 }
 
 void StackMap::Dump(VariableIndentationOutputStream* vios,
                     const CodeInfo& code_info,
-                    const MethodInfo& method_info,
                     uint32_t code_offset,
                     InstructionSet instruction_set) const {
   const uint32_t pc_offset = GetNativePcOffset(instruction_set);
@@ -312,14 +314,13 @@
   vios->Stream() << ")\n";
   code_info.GetDexRegisterMapOf(*this).Dump(vios);
   for (InlineInfo inline_info : code_info.GetInlineInfosOf(*this)) {
-    inline_info.Dump(vios, code_info, *this, method_info);
+    inline_info.Dump(vios, code_info, *this);
   }
 }
 
 void InlineInfo::Dump(VariableIndentationOutputStream* vios,
                       const CodeInfo& code_info,
-                      const StackMap& stack_map,
-                      const MethodInfo& method_info) const {
+                      const StackMap& stack_map) const {
   uint32_t depth = Row() - stack_map.GetInlineInfoIndex();
   vios->Stream()
       << "InlineInfo[" << Row() << "]"
@@ -332,7 +333,7 @@
   } else {
     vios->Stream()
         << std::dec
-        << ", method_index=" << GetMethodIndex(method_info);
+        << ", method_index=" << code_info.GetMethodIndexOf(*this);
   }
   vios->Stream() << ")\n";
   code_info.GetInlineDexRegisterMapOf(stack_map, *this).Dump(vios);
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 909aaa5..8bfae7c 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -28,7 +28,6 @@
 #include "base/memory_region.h"
 #include "dex/dex_file_types.h"
 #include "dex_register_location.h"
-#include "method_info.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -164,7 +163,6 @@
 
   void Dump(VariableIndentationOutputStream* vios,
             const CodeInfo& code_info,
-            const MethodInfo& method_info,
             uint32_t code_offset,
             InstructionSet instruction_set) const;
 };
@@ -188,10 +186,6 @@
   static constexpr uint32_t kLast = -1;
   static constexpr uint32_t kMore = 0;
 
-  uint32_t GetMethodIndex(const MethodInfo& method_info) const {
-    return method_info.GetMethodIndex(GetMethodInfoIndex());
-  }
-
   bool EncodesArtMethod() const {
     return HasArtMethodLo();
   }
@@ -204,8 +198,7 @@
 
   void Dump(VariableIndentationOutputStream* vios,
             const CodeInfo& info,
-            const StackMap& stack_map,
-            const MethodInfo& method_info) const;
+            const StackMap& stack_map) const;
 };
 
 class MaskInfo : public BitTableAccessor<1> {
@@ -262,6 +255,14 @@
   }
 };
 
+// Method indices are not very dedup friendly.
+// Separating them greatly improves dedup efficiency of the other tables.
+class MethodInfo : public BitTableAccessor<1> {
+ public:
+  BIT_TABLE_HEADER()
+  BIT_TABLE_COLUMN(0, MethodIndex)
+};
+
 /**
  * Wrapper around all compiler information collected for a method.
  * See the Decode method at the end for the precise binary format.
@@ -329,6 +330,10 @@
     return stack_maps_.NumRows();
   }
 
+  uint32_t GetMethodIndexOf(InlineInfo inline_info) const {
+    return method_infos_.GetRow(inline_info.GetMethodInfoIndex()).GetMethodIndex();
+  }
+
   ALWAYS_INLINE DexRegisterMap GetDexRegisterMapOf(StackMap stack_map) const {
     if (stack_map.HasDexRegisterMap()) {
       DexRegisterMap map(number_of_dex_registers_, DexRegisterLocation::Invalid());
@@ -405,8 +410,7 @@
   void Dump(VariableIndentationOutputStream* vios,
             uint32_t code_offset,
             bool verbose,
-            InstructionSet instruction_set,
-            const MethodInfo& method_info) const;
+            InstructionSet instruction_set) const;
 
   // Accumulate code info size statistics into the given Stats tree.
   void AddSizeStats(/*out*/ Stats* parent) const;
@@ -446,6 +450,7 @@
   uint32_t number_of_dex_registers_;
   BitTable<StackMap> stack_maps_;
   BitTable<InlineInfo> inline_infos_;
+  BitTable<MethodInfo> method_infos_;
   BitTable<RegisterMask> register_masks_;
   BitTable<MaskInfo> stack_masks_;
   BitTable<MaskInfo> dex_register_masks_;