Remove #include "oat_file.h" from class_linker.h .
Refactor the OatClass and OatMethod related functions from
ClassLinker to OatFile and ArtMethod, respectively. Refactor
the remaining ClassLinker dependencies on OatFile to break
the #include dependency and reduce incremental build times.
Test: m test-art-host
Change-Id: Iebc5b9f81b48fbcf79821cc827a5d7c4a0261bf6
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 0d3c012..6f24568 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2750,104 +2750,15 @@
image_pointer_size_);
}
-OatFile::OatClass ClassLinker::FindOatClass(const DexFile& dex_file,
- uint16_t class_def_idx,
- bool* found) {
- DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
- const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
- if (oat_dex_file == nullptr) {
- *found = false;
- return OatFile::OatClass::Invalid();
- }
- *found = true;
- return oat_dex_file->GetOatClass(class_def_idx);
-}
-
-static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
- uint16_t class_def_idx,
- uint32_t method_idx) {
- const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx);
- const uint8_t* class_data = dex_file.GetClassData(class_def);
- CHECK(class_data != nullptr);
- ClassDataItemIterator it(dex_file, class_data);
- // Skip fields
- while (it.HasNextStaticField()) {
- it.Next();
- }
- while (it.HasNextInstanceField()) {
- it.Next();
- }
- // Process methods
- size_t class_def_method_index = 0;
- while (it.HasNextDirectMethod()) {
- if (it.GetMemberIndex() == method_idx) {
- return class_def_method_index;
- }
- class_def_method_index++;
- it.Next();
- }
- while (it.HasNextVirtualMethod()) {
- if (it.GetMemberIndex() == method_idx) {
- return class_def_method_index;
- }
- class_def_method_index++;
- it.Next();
- }
- DCHECK(!it.HasNext());
- LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
- UNREACHABLE();
-}
-
-const OatFile::OatMethod ClassLinker::FindOatMethodFor(ArtMethod* method, bool* found) {
- // Although we overwrite the trampoline of non-static methods, we may get here via the resolution
- // method for direct methods (or virtual methods made direct).
- mirror::Class* declaring_class = method->GetDeclaringClass();
- size_t oat_method_index;
- if (method->IsStatic() || method->IsDirect()) {
- // Simple case where the oat method index was stashed at load time.
- oat_method_index = method->GetMethodIndex();
- } else {
- // We're invoking a virtual method directly (thanks to sharpening), compute the oat_method_index
- // by search for its position in the declared virtual methods.
- oat_method_index = declaring_class->NumDirectMethods();
- bool found_virtual = false;
- for (ArtMethod& art_method : declaring_class->GetVirtualMethods(image_pointer_size_)) {
- // Check method index instead of identity in case of duplicate method definitions.
- if (method->GetDexMethodIndex() == art_method.GetDexMethodIndex()) {
- found_virtual = true;
- break;
- }
- oat_method_index++;
- }
- CHECK(found_virtual) << "Didn't find oat method index for virtual method: "
- << PrettyMethod(method);
- }
- DCHECK_EQ(oat_method_index,
- GetOatMethodIndexFromMethodIndex(*declaring_class->GetDexCache()->GetDexFile(),
- method->GetDeclaringClass()->GetDexClassDefIndex(),
- method->GetDexMethodIndex()));
- OatFile::OatClass oat_class = FindOatClass(*declaring_class->GetDexCache()->GetDexFile(),
- declaring_class->GetDexClassDefIndex(),
- found);
- if (!(*found)) {
- return OatFile::OatMethod::Invalid();
- }
- return oat_class.GetOatMethod(oat_method_index);
-}
-
// Special case to get oat code without overwriting a trampoline.
const void* ClassLinker::GetQuickOatCodeFor(ArtMethod* method) {
CHECK(method->IsInvokable()) << PrettyMethod(method);
if (method->IsProxyMethod()) {
return GetQuickProxyInvokeHandler();
}
- bool found;
- OatFile::OatMethod oat_method = FindOatMethodFor(method, &found);
- if (found) {
- auto* code = oat_method.GetQuickCode();
- if (code != nullptr) {
- return code;
- }
+ auto* code = method->GetOatMethodQuickCode(GetImagePointerSize());
+ if (code != nullptr) {
+ return code;
}
if (method->IsNative()) {
// No code and native? Use generic trampoline.
@@ -2856,18 +2767,6 @@
return GetQuickToInterpreterBridge();
}
-const void* ClassLinker::GetOatMethodQuickCodeFor(ArtMethod* method) {
- if (method->IsNative() || !method->IsInvokable() || method->IsProxyMethod()) {
- return nullptr;
- }
- bool found;
- OatFile::OatMethod oat_method = FindOatMethodFor(method, &found);
- if (found) {
- return oat_method.GetQuickCode();
- }
- return nullptr;
-}
-
bool ClassLinker::ShouldUseInterpreterEntrypoint(ArtMethod* method, const void* quick_code) {
if (UNLIKELY(method->IsNative() || method->IsProxyMethod())) {
return false;
@@ -2938,9 +2837,9 @@
it.Next();
}
bool has_oat_class;
- OatFile::OatClass oat_class = FindOatClass(dex_file,
- klass->GetDexClassDefIndex(),
- &has_oat_class);
+ OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file,
+ klass->GetDexClassDefIndex(),
+ &has_oat_class);
// Link the code of methods skipped by LinkCode.
for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
@@ -2965,15 +2864,20 @@
// Ignore virtual methods on the iterator.
}
-void ClassLinker::EnsureThrowsInvocationError(ArtMethod* method) {
+// Does anything needed to make sure that the compiler will not generate a direct invoke to this
+// method. Should only be called on non-invokable methods.
+inline void EnsureThrowsInvocationError(ClassLinker* class_linker, ArtMethod* method) {
DCHECK(method != nullptr);
DCHECK(!method->IsInvokable());
- method->SetEntryPointFromQuickCompiledCodePtrSize(quick_to_interpreter_bridge_trampoline_,
- image_pointer_size_);
+ method->SetEntryPointFromQuickCompiledCodePtrSize(
+ class_linker->GetQuickToInterpreterBridgeTrampoline(),
+ class_linker->GetImagePointerSize());
}
-void ClassLinker::LinkCode(ArtMethod* method, const OatFile::OatClass* oat_class,
- uint32_t class_def_method_index) {
+static void LinkCode(ClassLinker* class_linker,
+ ArtMethod* method,
+ const OatFile::OatClass* oat_class,
+ uint32_t class_def_method_index) REQUIRES_SHARED(Locks::mutator_lock_) {
Runtime* const runtime = Runtime::Current();
if (runtime->IsAotCompiler()) {
// The following code only applies to a non-compiler runtime.
@@ -2990,10 +2894,10 @@
// Install entry point from interpreter.
const void* quick_code = method->GetEntryPointFromQuickCompiledCode();
- bool enter_interpreter = ShouldUseInterpreterEntrypoint(method, quick_code);
+ bool enter_interpreter = class_linker->ShouldUseInterpreterEntrypoint(method, quick_code);
if (!method->IsInvokable()) {
- EnsureThrowsInvocationError(method);
+ EnsureThrowsInvocationError(class_linker, method);
return;
}
@@ -3018,7 +2922,8 @@
// trampoline as entrypoint (non-static), or the resolution trampoline (static).
// TODO: this doesn't handle all the cases where trampolines may be installed.
const void* entry_point = method->GetEntryPointFromQuickCompiledCode();
- DCHECK(IsQuickGenericJniStub(entry_point) || IsQuickResolutionStub(entry_point));
+ DCHECK(class_linker->IsQuickGenericJniStub(entry_point) ||
+ class_linker->IsQuickResolutionStub(entry_point));
}
}
}
@@ -3054,17 +2959,7 @@
if (class_data == nullptr) {
return; // no fields or methods - for example a marker interface
}
- bool has_oat_class = false;
- if (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) {
- OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(),
- &has_oat_class);
- if (has_oat_class) {
- LoadClassMembers(self, dex_file, class_data, klass, &oat_class);
- }
- }
- if (!has_oat_class) {
- LoadClassMembers(self, dex_file, class_data, klass, nullptr);
- }
+ LoadClassMembers(self, dex_file, class_data, klass);
}
LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
@@ -3128,8 +3023,7 @@
void ClassLinker::LoadClassMembers(Thread* self,
const DexFile& dex_file,
const uint8_t* class_data,
- Handle<mirror::Class> klass,
- const OatFile::OatClass* oat_class) {
+ Handle<mirror::Class> klass) {
{
// Note: We cannot have thread suspension until the field and method arrays are setup or else
// Class::VisitFieldRoots may miss some fields or methods.
@@ -3189,6 +3083,12 @@
klass->SetIFieldsPtr(ifields);
DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
// Load methods.
+ bool has_oat_class = false;
+ const OatFile::OatClass oat_class =
+ (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
+ ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
+ : OatFile::OatClass::Invalid();
+ const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
klass->SetMethodsPtr(
AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
it.NumDirectMethods(),
@@ -3200,7 +3100,7 @@
for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
LoadMethod(dex_file, it, klass, method);
- LinkCode(method, oat_class, class_def_method_index);
+ LinkCode(this, method, oat_class_ptr, class_def_method_index);
uint32_t it_method_index = it.GetMemberIndex();
if (last_dex_method_index == it_method_index) {
// duplicate case
@@ -3216,7 +3116,7 @@
ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
LoadMethod(dex_file, it, klass, method);
DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
- LinkCode(method, oat_class, class_def_method_index);
+ LinkCode(this, method, oat_class_ptr, class_def_method_index);
class_def_method_index++;
}
DCHECK(!it.HasNext());
@@ -7185,7 +7085,7 @@
// The actual method might or might not be marked abstract since we just copied it from a
// (possibly default) interface method. We need to set it entry point to be the bridge so
// that the compiler will not invoke the implementation of whatever method we copied from.
- EnsureThrowsInvocationError(&new_method);
+ EnsureThrowsInvocationError(this, &new_method);
move_table.emplace(conf_method, &new_method);
++out;
}