ART: Factor out IMT from ArtMethod

Move IMT Conflict Table to its own file. Move IMT index computation to
ImTable.

In preparation for code using this independent of specific ArtMethods.

Bug: 31594153
Test: m test-art-host
Change-Id: Ifd6e304bb86724c5284984c4655c43d3af357f84
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index ad881b7..6b5758b 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -45,6 +45,7 @@
 #include "gc/space/space-inl.h"
 #include "globals.h"
 #include "image.h"
+#include "imt_conflict_table.h"
 #include "intern_table.h"
 #include "linear_alloc.h"
 #include "lock_word.h"
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 139daa7..3b08d9f 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -21,6 +21,7 @@
 #include "class_linker.h"
 #include "dex_instruction-inl.h"
 #include "driver/compiler_options.h"
+#include "imtable-inl.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
@@ -895,7 +896,7 @@
                                            dex_pc,
                                            method_idx,
                                            resolved_method,
-                                           resolved_method->GetImtIndex());
+                                           ImTable::GetImtIndex(resolved_method));
   }
 
   return HandleInvoke(invoke,
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 507dbf0..3424e3c 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -22,6 +22,7 @@
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
+#include "imt_conflict_table.h"
 #include "linear_alloc.h"
 #include "mirror/class-inl.h"
 #include "mirror/string-inl.h"
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 9b4b38a..73cce5e 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -123,10 +123,6 @@
   return dex_method_index_;
 }
 
-inline uint32_t ArtMethod::GetImtIndex() {
-  return GetDexMethodIndex() % ImTable::kSize;
-}
-
 inline ArtMethod** ArtMethod::GetDexCacheResolvedMethods(PointerSize pointer_size) {
   return GetNativePointer<ArtMethod**>(DexCacheResolvedMethodsOffset(pointer_size),
                                        pointer_size);
diff --git a/runtime/art_method.h b/runtime/art_method.h
index b1baccd..3d2db69 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -34,6 +34,7 @@
 namespace art {
 
 template<class T> class Handle;
+class ImtConflictTable;
 union JValue;
 class OatQuickMethodHeader;
 class ProfilingInfo;
@@ -48,175 +49,6 @@
 class PointerArray;
 }  // namespace mirror
 
-// Table to resolve IMT conflicts at runtime. The table is attached to
-// the jni entrypoint of IMT conflict ArtMethods.
-// The table contains a list of pairs of { interface_method, implementation_method }
-// with the last entry being null to make an assembly implementation of a lookup
-// faster.
-class ImtConflictTable {
-  enum MethodIndex {
-    kMethodInterface,
-    kMethodImplementation,
-    kMethodCount,  // Number of elements in enum.
-  };
-
- public:
-  // Build a new table copying `other` and adding the new entry formed of
-  // the pair { `interface_method`, `implementation_method` }
-  ImtConflictTable(ImtConflictTable* other,
-                   ArtMethod* interface_method,
-                   ArtMethod* implementation_method,
-                   PointerSize pointer_size) {
-    const size_t count = other->NumEntries(pointer_size);
-    for (size_t i = 0; i < count; ++i) {
-      SetInterfaceMethod(i, pointer_size, other->GetInterfaceMethod(i, pointer_size));
-      SetImplementationMethod(i, pointer_size, other->GetImplementationMethod(i, pointer_size));
-    }
-    SetInterfaceMethod(count, pointer_size, interface_method);
-    SetImplementationMethod(count, pointer_size, implementation_method);
-    // Add the null marker.
-    SetInterfaceMethod(count + 1, pointer_size, nullptr);
-    SetImplementationMethod(count + 1, pointer_size, nullptr);
-  }
-
-  // num_entries excludes the header.
-  ImtConflictTable(size_t num_entries, PointerSize pointer_size) {
-    SetInterfaceMethod(num_entries, pointer_size, nullptr);
-    SetImplementationMethod(num_entries, pointer_size, nullptr);
-  }
-
-  // Set an entry at an index.
-  void SetInterfaceMethod(size_t index, PointerSize pointer_size, ArtMethod* method) {
-    SetMethod(index * kMethodCount + kMethodInterface, pointer_size, method);
-  }
-
-  void SetImplementationMethod(size_t index, PointerSize pointer_size, ArtMethod* method) {
-    SetMethod(index * kMethodCount + kMethodImplementation, pointer_size, method);
-  }
-
-  ArtMethod* GetInterfaceMethod(size_t index, PointerSize pointer_size) const {
-    return GetMethod(index * kMethodCount + kMethodInterface, pointer_size);
-  }
-
-  ArtMethod* GetImplementationMethod(size_t index, PointerSize pointer_size) const {
-    return GetMethod(index * kMethodCount + kMethodImplementation, pointer_size);
-  }
-
-  // Return true if two conflict tables are the same.
-  bool Equals(ImtConflictTable* other, PointerSize pointer_size) const {
-    size_t num = NumEntries(pointer_size);
-    if (num != other->NumEntries(pointer_size)) {
-      return false;
-    }
-    for (size_t i = 0; i < num; ++i) {
-      if (GetInterfaceMethod(i, pointer_size) != other->GetInterfaceMethod(i, pointer_size) ||
-          GetImplementationMethod(i, pointer_size) !=
-              other->GetImplementationMethod(i, pointer_size)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  // Visit all of the entries.
-  // NO_THREAD_SAFETY_ANALYSIS for calling with held locks. Visitor is passed a pair of ArtMethod*
-  // and also returns one. The order is <interface, implementation>.
-  template<typename Visitor>
-  void Visit(const Visitor& visitor, PointerSize pointer_size) NO_THREAD_SAFETY_ANALYSIS {
-    uint32_t table_index = 0;
-    for (;;) {
-      ArtMethod* interface_method = GetInterfaceMethod(table_index, pointer_size);
-      if (interface_method == nullptr) {
-        break;
-      }
-      ArtMethod* implementation_method = GetImplementationMethod(table_index, pointer_size);
-      auto input = std::make_pair(interface_method, implementation_method);
-      std::pair<ArtMethod*, ArtMethod*> updated = visitor(input);
-      if (input.first != updated.first) {
-        SetInterfaceMethod(table_index, pointer_size, updated.first);
-      }
-      if (input.second != updated.second) {
-        SetImplementationMethod(table_index, pointer_size, updated.second);
-      }
-      ++table_index;
-    }
-  }
-
-  // Lookup the implementation ArtMethod associated to `interface_method`. Return null
-  // if not found.
-  ArtMethod* Lookup(ArtMethod* interface_method, PointerSize pointer_size) const {
-    uint32_t table_index = 0;
-    for (;;) {
-      ArtMethod* current_interface_method = GetInterfaceMethod(table_index, pointer_size);
-      if (current_interface_method == nullptr) {
-        break;
-      }
-      if (current_interface_method == interface_method) {
-        return GetImplementationMethod(table_index, pointer_size);
-      }
-      ++table_index;
-    }
-    return nullptr;
-  }
-
-  // Compute the number of entries in this table.
-  size_t NumEntries(PointerSize pointer_size) const {
-    uint32_t table_index = 0;
-    while (GetInterfaceMethod(table_index, pointer_size) != nullptr) {
-      ++table_index;
-    }
-    return table_index;
-  }
-
-  // Compute the size in bytes taken by this table.
-  size_t ComputeSize(PointerSize pointer_size) const {
-    // Add the end marker.
-    return ComputeSize(NumEntries(pointer_size), pointer_size);
-  }
-
-  // Compute the size in bytes needed for copying the given `table` and add
-  // one more entry.
-  static size_t ComputeSizeWithOneMoreEntry(ImtConflictTable* table, PointerSize pointer_size) {
-    return table->ComputeSize(pointer_size) + EntrySize(pointer_size);
-  }
-
-  // Compute size with a fixed number of entries.
-  static size_t ComputeSize(size_t num_entries, PointerSize pointer_size) {
-    return (num_entries + 1) * EntrySize(pointer_size);  // Add one for null terminator.
-  }
-
-  static size_t EntrySize(PointerSize pointer_size) {
-    return static_cast<size_t>(pointer_size) * static_cast<size_t>(kMethodCount);
-  }
-
- private:
-  ArtMethod* GetMethod(size_t index, PointerSize pointer_size) const {
-    if (pointer_size == PointerSize::k64) {
-      return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(data64_[index]));
-    } else {
-      return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(data32_[index]));
-    }
-  }
-
-  void SetMethod(size_t index, PointerSize pointer_size, ArtMethod* method) {
-    if (pointer_size == PointerSize::k64) {
-      data64_[index] = dchecked_integral_cast<uint64_t>(reinterpret_cast<uintptr_t>(method));
-    } else {
-      data32_[index] = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(method));
-    }
-  }
-
-  // Array of entries that the assembly stubs will iterate over. Note that this is
-  // not fixed size, and we allocate data prior to calling the constructor
-  // of ImtConflictTable.
-  union {
-    uint32_t data32_[0];
-    uint64_t data64_[0];
-  };
-
-  DISALLOW_COPY_AND_ASSIGN(ImtConflictTable);
-};
-
 class ArtMethod FINAL {
  public:
   ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0),
@@ -428,8 +260,6 @@
 
   ALWAYS_INLINE uint32_t GetDexMethodIndex() REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE uint32_t GetImtIndex() REQUIRES_SHARED(Locks::mutator_lock_);
-
   void SetDexMethodIndex(uint32_t new_idx) {
     // Not called within a transaction.
     dex_method_index_ = new_idx;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index ecaa4c2..c51b99a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,6 +56,8 @@
 #include "gc/space/image_space.h"
 #include "handle_scope-inl.h"
 #include "image-inl.h"
+#include "imt_conflict_table.h"
+#include "imtable-inl.h"
 #include "intern_table.h"
 #include "interpreter/interpreter.h"
 #include "jit/jit.h"
@@ -6268,7 +6270,7 @@
       // or interface methods in the IMT here they will not create extra conflicts since we compare
       // names and signatures in SetIMTRef.
       ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size_);
-      const uint32_t imt_index = interface_method->GetImtIndex();
+      const uint32_t imt_index = ImTable::GetImtIndex(interface_method);
 
       // There is only any conflicts if all of the interface methods for an IMT slot don't have
       // the same implementation method, keep track of this to avoid creating a conflict table in
@@ -6322,7 +6324,7 @@
         }
         DCHECK(implementation_method != nullptr);
         ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size_);
-        const uint32_t imt_index = interface_method->GetImtIndex();
+        const uint32_t imt_index = ImTable::GetImtIndex(interface_method);
         if (!imt[imt_index]->IsRuntimeMethod() ||
             imt[imt_index] == unimplemented_method ||
             imt[imt_index] == imt_conflict_method) {
@@ -6781,7 +6783,7 @@
         auto* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j, image_pointer_size_);
         MethodNameAndSignatureComparator interface_name_comparator(
             interface_method->GetInterfaceMethodIfProxy(image_pointer_size_));
-        uint32_t imt_index = interface_method->GetImtIndex();
+        uint32_t imt_index = ImTable::GetImtIndex(interface_method);
         ArtMethod** imt_ptr = &out_imt[imt_index];
         // For each method listed in the interface's method list, find the
         // matching method in our class's method list.  We want to favor the
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 14110c2..99b8805 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -26,6 +26,8 @@
 #include "dex_file.h"
 #include "entrypoints/quick/callee_save_frame.h"
 #include "handle_scope-inl.h"
+#include "imt_conflict_table.h"
+#include "imtable-inl.h"
 #include "indirect_reference_table.h"
 #include "invoke_type.h"
 #include "jni_internal.h"
@@ -612,7 +614,7 @@
       UNREACHABLE();
     }
     case kInterface: {
-      uint32_t imt_index = resolved_method->GetImtIndex();
+      uint32_t imt_index = ImTable::GetImtIndex(resolved_method);
       PointerSize pointer_size = class_linker->GetImagePointerSize();
       ArtMethod* imt_method = (*this_object)->GetClass()->GetImt(pointer_size)->
           Get(imt_index, pointer_size);
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index fcbd834..cfd948e 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -23,6 +23,8 @@
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "gc/accounting/card_table-inl.h"
+#include "imt_conflict_table.h"
+#include "imtable-inl.h"
 #include "interpreter/interpreter.h"
 #include "linear_alloc.h"
 #include "method_reference.h"
@@ -2239,7 +2241,8 @@
   if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex)) {
     // If the dex cache already resolved the interface method, look whether we have
     // a match in the ImtConflictTable.
-    ArtMethod* conflict_method = imt->Get(interface_method->GetImtIndex(), kRuntimePointerSize);
+    ArtMethod* conflict_method = imt->Get(ImTable::GetImtIndex(interface_method),
+                                          kRuntimePointerSize);
     if (LIKELY(conflict_method->IsRuntimeMethod())) {
       ImtConflictTable* current_table = conflict_method->GetImtConflictTable(kRuntimePointerSize);
       DCHECK(current_table != nullptr);
@@ -2291,7 +2294,7 @@
 
   // We arrive here if we have found an implementation, and it is not in the ImtConflictTable.
   // We create a new table with the new pair { interface_method, method }.
-  uint32_t imt_index = interface_method->GetImtIndex();
+  uint32_t imt_index = ImTable::GetImtIndex(interface_method);
   ArtMethod* conflict_method = imt->Get(imt_index, kRuntimePointerSize);
   if (conflict_method->IsRuntimeMethod()) {
     ArtMethod* new_conflict_method = Runtime::Current()->GetClassLinker()->AddMethodToConflictTable(
diff --git a/runtime/image-inl.h b/runtime/image-inl.h
index 669649e..da18ae5 100644
--- a/runtime/image-inl.h
+++ b/runtime/image-inl.h
@@ -20,6 +20,7 @@
 #include "image.h"
 
 #include "art_method.h"
+#include "imt_conflict_table.h"
 #include "imtable.h"
 #include "read_barrier-inl.h"
 
diff --git a/runtime/imt_conflict_table.h b/runtime/imt_conflict_table.h
new file mode 100644
index 0000000..fdd10fe
--- /dev/null
+++ b/runtime/imt_conflict_table.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2016 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_IMT_CONFLICT_TABLE_H_
+#define ART_RUNTIME_IMT_CONFLICT_TABLE_H_
+
+#include <cstddef>
+
+#include "base/casts.h"
+#include "base/enums.h"
+#include "base/macros.h"
+
+namespace art {
+
+class ArtMethod;
+
+// Table to resolve IMT conflicts at runtime. The table is attached to
+// the jni entrypoint of IMT conflict ArtMethods.
+// The table contains a list of pairs of { interface_method, implementation_method }
+// with the last entry being null to make an assembly implementation of a lookup
+// faster.
+class ImtConflictTable {
+  enum MethodIndex {
+    kMethodInterface,
+    kMethodImplementation,
+    kMethodCount,  // Number of elements in enum.
+  };
+
+ public:
+  // Build a new table copying `other` and adding the new entry formed of
+  // the pair { `interface_method`, `implementation_method` }
+  ImtConflictTable(ImtConflictTable* other,
+                   ArtMethod* interface_method,
+                   ArtMethod* implementation_method,
+                   PointerSize pointer_size) {
+    const size_t count = other->NumEntries(pointer_size);
+    for (size_t i = 0; i < count; ++i) {
+      SetInterfaceMethod(i, pointer_size, other->GetInterfaceMethod(i, pointer_size));
+      SetImplementationMethod(i, pointer_size, other->GetImplementationMethod(i, pointer_size));
+    }
+    SetInterfaceMethod(count, pointer_size, interface_method);
+    SetImplementationMethod(count, pointer_size, implementation_method);
+    // Add the null marker.
+    SetInterfaceMethod(count + 1, pointer_size, nullptr);
+    SetImplementationMethod(count + 1, pointer_size, nullptr);
+  }
+
+  // num_entries excludes the header.
+  ImtConflictTable(size_t num_entries, PointerSize pointer_size) {
+    SetInterfaceMethod(num_entries, pointer_size, nullptr);
+    SetImplementationMethod(num_entries, pointer_size, nullptr);
+  }
+
+  // Set an entry at an index.
+  void SetInterfaceMethod(size_t index, PointerSize pointer_size, ArtMethod* method) {
+    SetMethod(index * kMethodCount + kMethodInterface, pointer_size, method);
+  }
+
+  void SetImplementationMethod(size_t index, PointerSize pointer_size, ArtMethod* method) {
+    SetMethod(index * kMethodCount + kMethodImplementation, pointer_size, method);
+  }
+
+  ArtMethod* GetInterfaceMethod(size_t index, PointerSize pointer_size) const {
+    return GetMethod(index * kMethodCount + kMethodInterface, pointer_size);
+  }
+
+  ArtMethod* GetImplementationMethod(size_t index, PointerSize pointer_size) const {
+    return GetMethod(index * kMethodCount + kMethodImplementation, pointer_size);
+  }
+
+  // Return true if two conflict tables are the same.
+  bool Equals(ImtConflictTable* other, PointerSize pointer_size) const {
+    size_t num = NumEntries(pointer_size);
+    if (num != other->NumEntries(pointer_size)) {
+      return false;
+    }
+    for (size_t i = 0; i < num; ++i) {
+      if (GetInterfaceMethod(i, pointer_size) != other->GetInterfaceMethod(i, pointer_size) ||
+          GetImplementationMethod(i, pointer_size) !=
+              other->GetImplementationMethod(i, pointer_size)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  // Visit all of the entries.
+  // NO_THREAD_SAFETY_ANALYSIS for calling with held locks. Visitor is passed a pair of ArtMethod*
+  // and also returns one. The order is <interface, implementation>.
+  template<typename Visitor>
+  void Visit(const Visitor& visitor, PointerSize pointer_size) NO_THREAD_SAFETY_ANALYSIS {
+    uint32_t table_index = 0;
+    for (;;) {
+      ArtMethod* interface_method = GetInterfaceMethod(table_index, pointer_size);
+      if (interface_method == nullptr) {
+        break;
+      }
+      ArtMethod* implementation_method = GetImplementationMethod(table_index, pointer_size);
+      auto input = std::make_pair(interface_method, implementation_method);
+      std::pair<ArtMethod*, ArtMethod*> updated = visitor(input);
+      if (input.first != updated.first) {
+        SetInterfaceMethod(table_index, pointer_size, updated.first);
+      }
+      if (input.second != updated.second) {
+        SetImplementationMethod(table_index, pointer_size, updated.second);
+      }
+      ++table_index;
+    }
+  }
+
+  // Lookup the implementation ArtMethod associated to `interface_method`. Return null
+  // if not found.
+  ArtMethod* Lookup(ArtMethod* interface_method, PointerSize pointer_size) const {
+    uint32_t table_index = 0;
+    for (;;) {
+      ArtMethod* current_interface_method = GetInterfaceMethod(table_index, pointer_size);
+      if (current_interface_method == nullptr) {
+        break;
+      }
+      if (current_interface_method == interface_method) {
+        return GetImplementationMethod(table_index, pointer_size);
+      }
+      ++table_index;
+    }
+    return nullptr;
+  }
+
+  // Compute the number of entries in this table.
+  size_t NumEntries(PointerSize pointer_size) const {
+    uint32_t table_index = 0;
+    while (GetInterfaceMethod(table_index, pointer_size) != nullptr) {
+      ++table_index;
+    }
+    return table_index;
+  }
+
+  // Compute the size in bytes taken by this table.
+  size_t ComputeSize(PointerSize pointer_size) const {
+    // Add the end marker.
+    return ComputeSize(NumEntries(pointer_size), pointer_size);
+  }
+
+  // Compute the size in bytes needed for copying the given `table` and add
+  // one more entry.
+  static size_t ComputeSizeWithOneMoreEntry(ImtConflictTable* table, PointerSize pointer_size) {
+    return table->ComputeSize(pointer_size) + EntrySize(pointer_size);
+  }
+
+  // Compute size with a fixed number of entries.
+  static size_t ComputeSize(size_t num_entries, PointerSize pointer_size) {
+    return (num_entries + 1) * EntrySize(pointer_size);  // Add one for null terminator.
+  }
+
+  static size_t EntrySize(PointerSize pointer_size) {
+    return static_cast<size_t>(pointer_size) * static_cast<size_t>(kMethodCount);
+  }
+
+ private:
+  ArtMethod* GetMethod(size_t index, PointerSize pointer_size) const {
+    if (pointer_size == PointerSize::k64) {
+      return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(data64_[index]));
+    } else {
+      return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(data32_[index]));
+    }
+  }
+
+  void SetMethod(size_t index, PointerSize pointer_size, ArtMethod* method) {
+    if (pointer_size == PointerSize::k64) {
+      data64_[index] = dchecked_integral_cast<uint64_t>(reinterpret_cast<uintptr_t>(method));
+    } else {
+      data32_[index] = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(method));
+    }
+  }
+
+  // Array of entries that the assembly stubs will iterate over. Note that this is
+  // not fixed size, and we allocate data prior to calling the constructor
+  // of ImtConflictTable.
+  union {
+    uint32_t data32_[0];
+    uint64_t data64_[0];
+  };
+
+  DISALLOW_COPY_AND_ASSIGN(ImtConflictTable);
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_IMT_CONFLICT_TABLE_H_
diff --git a/runtime/imtable-inl.h b/runtime/imtable-inl.h
new file mode 100644
index 0000000..0cb9b5e
--- /dev/null
+++ b/runtime/imtable-inl.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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_IMTABLE_INL_H_
+#define ART_RUNTIME_IMTABLE_INL_H_
+
+#include "imtable.h"
+
+#include "art_method-inl.h"
+
+namespace art {
+
+inline uint32_t ImTable::GetBaseImtHash(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+  return method->GetDexMethodIndex();
+}
+
+inline uint32_t ImTable::GetImtIndex(ArtMethod* method) {
+  return GetBaseImtHash(method) % ImTable::kSize;
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_IMTABLE_INL_H_
+
diff --git a/runtime/imtable.h b/runtime/imtable.h
index 2416621..6df890d 100644
--- a/runtime/imtable.h
+++ b/runtime/imtable.h
@@ -21,9 +21,13 @@
 #error IMT_SIZE not defined
 #endif
 
+#include "base/enums.h"
+#include "base/macros.h"
+
 namespace art {
 
 class ArtMethod;
+class DexFile;
 
 class ImTable {
  public:
@@ -69,6 +73,19 @@
   constexpr static size_t SizeInBytes(PointerSize pointer_size) {
     return kSize * static_cast<size_t>(pointer_size);
   }
+
+  // Converts a method to the base hash used in GetImtIndex.
+  ALWAYS_INLINE static inline uint32_t GetBaseImtHash(ArtMethod* method)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  ALWAYS_INLINE static inline uint32_t GetBaseImtHash(const DexFile* dex_file, uint32_t method_idx)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // The (complete) hashing scheme to map an ArtMethod to a slot in the Interface Method Table
+  // (IMT).
+  ALWAYS_INLINE static inline uint32_t GetImtIndex(ArtMethod* method)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  ALWAYS_INLINE static inline uint32_t GetImtIndex(const DexFile* dex_file, uint32_t method_idx)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 };
 
 }  // namespace art