Add ELF loader to load the executables.
(cherry picked from commit 8c9ca414a7ed05c3530973c63496e477e9ca5eb7)
Conflicts:
src/compiler.cc
Change-Id: I950749625d5b266990c617e2d8cea688fbdc11fb
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 84e66de..1d878c9 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -18,8 +18,10 @@
#include "class_linker.h"
#include "compilation_unit.h"
+#include "compiled_method.h"
#include "compiler.h"
#include "dex_cache.h"
+#include "elf_loader.h"
#include "ir_builder.h"
#include "jni_compiler.h"
#include "method_compiler.h"
@@ -166,11 +168,64 @@
// Materialize the llvm::Module into ELF object file
curr_cunit_->Materialize();
+ // Load ELF image when automatic ELF loading is enabled
+ if (IsAutoElfLoadingEnabled()) {
+ LoadElfFromCompilationUnit(curr_cunit_);
+ }
+
// Delete the compilation unit
curr_cunit_ = NULL;
}
+void CompilerLLVM::EnableAutoElfLoading() {
+ MutexLock GUARD(compiler_lock_);
+
+ if (IsAutoElfLoadingEnabled()) {
+ // If there is an existing ELF loader, then do nothing.
+ // Because the existing ELF loader may have returned some code address
+ // already. If we replace the existing ELF loader with
+ // elf_loader_.reset(...), then it is possible to have some dangling
+ // pointer.
+ return;
+ }
+
+ // Create ELF loader and load the materialized CompilationUnit
+ elf_loader_.reset(new ElfLoader());
+
+ for (size_t i = 0; i < cunits_.size(); ++i) {
+ if (cunits_[i]->IsMaterialized()) {
+ LoadElfFromCompilationUnit(cunits_[i]);
+ }
+ }
+}
+
+
+void CompilerLLVM::LoadElfFromCompilationUnit(const CompilationUnit* cunit) {
+ compiler_lock_.AssertHeld();
+ DCHECK(cunit->IsMaterialized()) << cunit->GetElfIndex();
+
+ if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(),
+ cunit->GetElfImage(),
+ cunit->GetElfSize())) {
+ LOG(ERROR) << "Failed to load ELF from compilation unit "
+ << cunit->GetElfIndex();
+ }
+}
+
+
+const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm,
+ const Method* method) const {
+ return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(), method);
+}
+
+
+const Method::InvokeStub* CompilerLLVM::
+GetMethodInvokeStubAddr(const CompiledInvokeStub* cm, const Method* method) const {
+ return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(), method);
+}
+
+
CompiledMethod* CompilerLLVM::
CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
MutexLock GUARD(compiler_lock_);
@@ -286,6 +341,28 @@
ContextOf(compiler)->MaterializeRemainder();
}
+extern "C" void compilerLLVMEnableAutoElfLoading(art::Compiler& compiler) {
+ art::compiler_llvm::CompilerLLVM* compiler_llvm =
+ reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
+ return compiler_llvm->EnableAutoElfLoading();
+}
+
+extern "C" const void* compilerLLVMGetMethodCodeAddr(const art::Compiler& compiler,
+ const art::CompiledMethod* cm,
+ const art::Method* method) {
+ const art::compiler_llvm::CompilerLLVM* compiler_llvm =
+ reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
+ return compiler_llvm->GetMethodCodeAddr(cm, method);
+}
+
+extern "C" const art::Method::InvokeStub* compilerLLVMGetMethodInvokeStubAddr(const art::Compiler& compiler,
+ const art::CompiledInvokeStub* cm,
+ const art::Method* method) {
+ const art::compiler_llvm::CompilerLLVM* compiler_llvm =
+ reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
+ return compiler_llvm->GetMethodInvokeStubAddr(cm, method);
+}
+
// Note: Using this function carefully!!! This is temporary solution, we will remove it.
extern "C" art::MutexLock* compilerLLVMMutexLock(art::Compiler& compiler) {
return new art::MutexLock(ContextOf(compiler)->compiler_lock_);