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