Move mapping table and vmap table offsets to OatMethodHeader.
This change has a libcore/ companion CL
"Remove ArtMethod's quick fields mapping table and vmap table."
https://android-review.googlesource.com/91254
Bug: 11767815
Change-Id: I46ce2067e1ecd915da3890606498e31ffc332813
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 5d62b88..6e1f062 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -78,13 +78,11 @@
inline uint32_t ArtMethod::GetCodeSize() {
DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
- uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode());
- if (code == 0) {
- return 0;
+ const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode());
+ if (code == nullptr) {
+ return 0u;
}
- // TODO: make this Thumb2 specific
- code &= ~0x1;
- return reinterpret_cast<OatMethodHeader*>(code)[-1].code_size_;
+ return reinterpret_cast<const OatMethodHeader*>(code)[-1].code_size_;
}
inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
@@ -124,7 +122,8 @@
return;
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (code == GetQuickResolutionTrampoline(class_linker)) {
+ if (code == GetQuickResolutionTrampoline(class_linker) ||
+ code == GetQuickToInterpreterBridgeTrampoline(class_linker)) {
return;
}
DCHECK(IsWithinQuickCode(pc))
@@ -154,26 +153,6 @@
SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(code_offset));
}
-inline uint32_t ArtMethod::GetOatMappingTableOffset() {
- DCHECK(!Runtime::Current()->IsStarted());
- return PointerToLowMemUInt32(GetMappingTable());
-}
-
-inline void ArtMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) {
- DCHECK(!Runtime::Current()->IsStarted());
- SetMappingTable(reinterpret_cast<const uint8_t*>(mapping_table_offset));
-}
-
-inline uint32_t ArtMethod::GetOatVmapTableOffset() {
- DCHECK(!Runtime::Current()->IsStarted());
- return PointerToLowMemUInt32(GetVmapTable());
-}
-
-inline void ArtMethod::SetOatVmapTableOffset(uint32_t vmap_table_offset) {
- DCHECK(!Runtime::Current()->IsStarted());
- SetVmapTable(reinterpret_cast<uint8_t*>(vmap_table_offset));
-}
-
inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) {
DCHECK(!Runtime::Current()->IsStarted());
SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset));
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index ee5a0a4..8da57bd 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -374,5 +374,43 @@
RegisterNative(self, GetJniDlsymLookupStub(), false);
}
+const void* ArtMethod::GetOatCodePointer() {
+ if (IsPortableCompiled() || IsNative() || IsAbstract() || IsRuntimeMethod() || IsProxyMethod()) {
+ return nullptr;
+ }
+ Runtime* runtime = Runtime::Current();
+ const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this);
+ // On failure, instead of nullptr we get the quick-to-interpreter-bridge (but not the trampoline).
+ DCHECK(entry_point != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker()));
+ if (entry_point == GetQuickToInterpreterBridge()) {
+ return nullptr;
+ }
+ return EntryPointToCodePointer(entry_point);
+}
+
+const uint8_t* ArtMethod::GetMappingTable() {
+ const void* code = GetOatCodePointer();
+ if (code == nullptr) {
+ return nullptr;
+ }
+ uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].mapping_table_offset_;
+ if (UNLIKELY(offset == 0u)) {
+ return nullptr;
+ }
+ return reinterpret_cast<const uint8_t*>(code) - offset;
+}
+
+const uint8_t* ArtMethod::GetVmapTable() {
+ const void* code = GetOatCodePointer();
+ if (code == nullptr) {
+ return nullptr;
+ }
+ uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].vmap_table_offset_;
+ if (UNLIKELY(offset == 0u)) {
+ return nullptr;
+ }
+ return reinterpret_cast<const uint8_t*>(code) - offset;
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index ee23c40..8d2c39c 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -21,6 +21,7 @@
#include "dex_file.h"
#include "invoke_type.h"
#include "modifiers.h"
+#include "oat.h"
#include "object.h"
#include "object_callbacks.h"
@@ -261,7 +262,6 @@
EntryPointFromQuickCompiledCodeOffset(), entry_point_from_quick_compiled_code, false);
}
-
uint32_t GetCodeSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -286,37 +286,20 @@
void SetQuickOatCodeOffset(uint32_t code_offset);
void SetPortableOatCodeOffset(uint32_t code_offset);
+ static const void* EntryPointToCodePointer(const void* entry_point) ALWAYS_INLINE {
+ uintptr_t code = reinterpret_cast<uintptr_t>(entry_point);
+ code &= ~0x1; // TODO: Make this Thumb2 specific.
+ return reinterpret_cast<const void*>(code);
+ }
+
+ // Actual pointer to compiled oat code or nullptr.
+ const void* GetOatCodePointer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Callers should wrap the uint8_t* in a MappingTable instance for convenient access.
- const uint8_t* GetMappingTable() {
- return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_),
- false);
- }
-
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- void SetMappingTable(const uint8_t* mapping_table) {
- SetFieldPtr<false, true, kVerifyFlags>(
- OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_), mapping_table, false);
- }
-
- uint32_t GetOatMappingTableOffset();
-
- void SetOatMappingTableOffset(uint32_t mapping_table_offset);
+ const uint8_t* GetMappingTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Callers should wrap the uint8_t* in a VmapTable instance for convenient access.
- const uint8_t* GetVmapTable() {
- return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_),
- false);
- }
-
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- void SetVmapTable(const uint8_t* vmap_table) {
- SetFieldPtr<false, true, kVerifyFlags>(
- OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table, false);
- }
-
- uint32_t GetOatVmapTableOffset();
-
- void SetOatVmapTableOffset(uint32_t vmap_table_offset);
+ const uint8_t* GetVmapTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const uint8_t* GetNativeGcMap() {
return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), false);
@@ -468,20 +451,6 @@
// offsets for the quick compiler and dex PCs for the portable.
uint64_t gc_map_;
- // --- Quick compiler meta-data. ---
- // TODO: merge and place in native heap, such as done with the code size.
-
- // Pointer to a data structure created by the quick compiler to map between dex PCs and native
- // PCs, and vice-versa.
- uint64_t quick_mapping_table_;
-
- // When a register is promoted into a register, the spill mask holds which registers hold dex
- // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth
- // is vmap_table_[N]. vmap_table_[0] holds the length of the table.
- uint64_t quick_vmap_table_;
-
- // --- End of quick compiler meta-data. ---
-
// Access flags; low 16 bits are defined by spec.
uint32_t access_flags_;