libart-compiler cleanup
- Move compile-time code to src/compiler and libart-compiler
OatWriter, ImageWriter, ElfWriter, ElfFixup, ElfStripper, stub generation
- Move ClassReference and MethodReference to remove MethodVerifier dependency on CompilerDriver
- Move runtime_support_llvm.cc out of src/compiler and next to runtime_support.cc
- Change dex2oat and gtests to directly depend on libart-compiler
- Move non-common definitions from Android.common.mk to more specific makefiles
- Add LOCAL_ADDITIONAL_DEPENDENCIES on appropriate makefiles
Change-Id: I897027e69945914128f21f317a92caf9255bc600
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index c8ccbe9..c876252 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -18,7 +18,6 @@
#include <vector>
-#include <dlfcn.h>
#include <unistd.h>
#include "base/stl_util.h"
@@ -48,8 +47,10 @@
#include "thread_pool.h"
#include "verifier/method_verifier.h"
-#if defined(__APPLE__)
-#include <mach-o/dyld.h>
+#if defined(ART_USE_PORTABLE_COMPILER)
+#include "compiler/elf_writer_mclinker.h"
+#else
+#include "compiler/elf_writer_quick.h"
#endif
namespace art {
@@ -281,48 +282,57 @@
DISALLOW_COPY_AND_ASSIGN(AOTCompilationStats);
};
-static std::string MakeCompilerSoName(CompilerBackend compiler_backend) {
+extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver);
+extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& compiler);
- // Bad things happen if we pull in the libartd-compiler to a libart dex2oat or vice versa,
- // because we end up with both libart and libartd in the same address space!
- const char* suffix = (kIsDebugBuild ? "d" : "");
+extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
+extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& compiler);
- // Work out the filename for the compiler library.
- std::string library_name(StringPrintf("art%s-compiler", suffix));
- std::string filename(StringPrintf(OS_SHARED_LIB_FORMAT_STR, library_name.c_str()));
+extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
+ const art::DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ art::InvokeType invoke_type,
+ uint32_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const art::DexFile& dex_file);
+extern "C" art::CompiledMethod* ArtQuickCompileMethod(art::CompilerDriver& compiler,
+ const art::DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ art::InvokeType invoke_type,
+ uint32_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const art::DexFile& dex_file);
-#if defined(__APPLE__)
- // On Linux, dex2oat will have been built with an RPATH of $ORIGIN/../lib, so dlopen(3) will find
- // the .so by itself. On Mac OS, there isn't really an equivalent, so we have to manually do the
- // same work.
- uint32_t executable_path_length = 0;
- _NSGetExecutablePath(NULL, &executable_path_length);
- std::string path(executable_path_length, static_cast<char>(0));
- CHECK_EQ(_NSGetExecutablePath(&path[0], &executable_path_length), 0);
+extern "C" art::CompiledMethod* ArtCompileDEX(art::CompilerDriver& compiler,
+ const art::DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ art::InvokeType invoke_type,
+ uint32_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const art::DexFile& dex_file);
- // Strip the "/dex2oat".
- size_t last_slash = path.find_last_of('/');
- CHECK_NE(last_slash, std::string::npos) << path;
- path.resize(last_slash);
+extern "C" art::CompiledMethod* SeaIrCompileMethod(art::CompilerDriver& compiler,
+ const art::DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ art::InvokeType invoke_type,
+ uint32_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const art::DexFile& dex_file);
- // Strip the "/bin".
- last_slash = path.find_last_of('/');
- path.resize(last_slash);
+extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
+ uint32_t access_flags, uint32_t method_idx,
+ const art::DexFile& dex_file);
- filename = path + "/lib/" + filename;
-#endif
- return filename;
-}
+extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver& compiler,
+ uint32_t access_flags, uint32_t method_idx,
+ const art::DexFile& dex_file);
-template<typename Fn>
-static Fn FindFunction(const std::string& compiler_so_name, void* library, const char* name) {
- Fn fn = reinterpret_cast<Fn>(dlsym(library, name));
- if (fn == NULL) {
- LOG(FATAL) << "Couldn't find \"" << name << "\" in compiler library " << compiler_so_name << ": " << dlerror();
- }
- VLOG(compiler) << "Found \"" << name << "\" at " << reinterpret_cast<void*>(fn);
- return fn;
-}
+extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver& driver,
+ std::string const& filename);
CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set,
bool image, DescriptorSet* image_classes,
@@ -349,13 +359,6 @@
compiler_get_method_code_addr_(NULL),
support_boot_image_fixup_(true)
{
- std::string compiler_so_name(MakeCompilerSoName(compiler_backend_));
- compiler_library_ = dlopen(compiler_so_name.c_str(), RTLD_LAZY);
- if (compiler_library_ == NULL) {
- LOG(FATAL) << "Couldn't find compiler library " << compiler_so_name << ": " << dlerror();
- }
- VLOG(compiler) << "dlopen(\"" << compiler_so_name << "\", RTLD_LAZY) returned " << compiler_library_;
-
CHECK_PTHREAD_CALL(pthread_key_create, (&tls_key_, NULL), "compiler tls key");
// TODO: more work needed to combine initializations and allow per-method backend selection
@@ -363,28 +366,28 @@
InitCompilerContextFn init_compiler_context;
if (compiler_backend_ == kPortable){
// Initialize compiler_context_
- init_compiler_context = FindFunction<void (*)(CompilerDriver&)>(compiler_so_name,
- compiler_library_, "ArtInitCompilerContext");
- compiler_ = FindFunction<CompilerFn>(compiler_so_name, compiler_library_, "ArtCompileMethod");
+ init_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtInitCompilerContext);
+ compiler_ = reinterpret_cast<CompilerFn>(ArtCompileMethod);
} else {
- init_compiler_context = FindFunction<void (*)(CompilerDriver&)>(compiler_so_name,
- compiler_library_, "ArtInitQuickCompilerContext");
- compiler_ = FindFunction<CompilerFn>(compiler_so_name, compiler_library_, "ArtQuickCompileMethod");
+ init_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtInitQuickCompilerContext);
+ compiler_ = reinterpret_cast<CompilerFn>(ArtQuickCompileMethod);
}
- dex_to_dex_compiler_ = FindFunction<CompilerFn>(compiler_so_name, compiler_library_, "ArtCompileDEX");
+ dex_to_dex_compiler_ = reinterpret_cast<CompilerFn>(ArtCompileDEX);
+#ifdef ART_SEA_IR_MODE
sea_ir_compiler_ = NULL;
if (Runtime::Current()->IsSeaIRMode()) {
- sea_ir_compiler_ = FindFunction<CompilerFn>(compiler_so_name, compiler_library_, "SeaIrCompileMethod");
+ sea_ir_compiler_ = reinterpret_cast<CompilerFn>(SeaIrCompileMethod);
}
+#endif
init_compiler_context(*this);
if (compiler_backend_ == kPortable) {
- jni_compiler_ = FindFunction<JniCompilerFn>(compiler_so_name, compiler_library_, "ArtLLVMJniCompileMethod");
+ jni_compiler_ = reinterpret_cast<JniCompilerFn>(ArtLLVMJniCompileMethod);
} else {
- jni_compiler_ = FindFunction<JniCompilerFn>(compiler_so_name, compiler_library_, "ArtQuickJniCompileMethod");
+ jni_compiler_ = reinterpret_cast<JniCompilerFn>(ArtQuickJniCompileMethod);
}
CHECK(!Runtime::Current()->IsStarted());
@@ -413,39 +416,15 @@
}
CHECK_PTHREAD_CALL(pthread_key_delete, (tls_key_), "delete tls key");
typedef void (*UninitCompilerContextFn)(CompilerDriver&);
- std::string compiler_so_name(MakeCompilerSoName(compiler_backend_));
UninitCompilerContextFn uninit_compiler_context;
// Uninitialize compiler_context_
// TODO: rework to combine initialization/uninitialization
if (compiler_backend_ == kPortable) {
- uninit_compiler_context = FindFunction<void (*)(CompilerDriver&)>(compiler_so_name,
- compiler_library_, "ArtUnInitCompilerContext");
+ uninit_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtUnInitCompilerContext);
} else {
- uninit_compiler_context = FindFunction<void (*)(CompilerDriver&)>(compiler_so_name,
- compiler_library_, "ArtUnInitQuickCompilerContext");
+ uninit_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtUnInitQuickCompilerContext);
}
uninit_compiler_context(*this);
-#if 0
- if (compiler_library_ != NULL) {
- VLOG(compiler) << "dlclose(" << compiler_library_ << ")";
- /*
- * FIXME: Temporary workaround
- * Apparently, llvm is adding dctors to atexit, but if we unload
- * the library here the code will no longer be around at exit time
- * and we die a flaming death in __cxa_finalize(). Apparently, some
- * dlclose() implementations will scan the atexit list on unload and
- * handle any associated with the soon-to-be-unloaded library.
- * However, this is not required by POSIX and we don't do it.
- * See: http://b/issue?id=4998315
- * What's the right thing to do here?
- *
- * This has now been completely disabled because mclinker was
- * closing stdout on exit, which was affecting both quick and
- * portable.
- */
- dlclose(compiler_library_);
- }
-#endif
}
CompilerTls* CompilerDriver::GetTls() {
@@ -1217,9 +1196,8 @@
if (kEnableVerifierBasedSharpening && (invoke_type == kVirtual ||
invoke_type == kInterface)) {
// Did the verifier record a more precise invoke target based on its type information?
- const CompilerDriver::MethodReference caller_method(mUnit->GetDexFile(),
- mUnit->GetDexMethodIndex());
- const CompilerDriver::MethodReference* devirt_map_target =
+ const MethodReference caller_method(mUnit->GetDexFile(), mUnit->GetDexMethodIndex());
+ const MethodReference* devirt_map_target =
verifier::MethodVerifier::GetDevirtMap(caller_method, dex_pc);
if (devirt_map_target != NULL) {
mirror::DexCache* target_dex_cache =
@@ -2138,7 +2116,7 @@
}
// Record the final class status if necessary.
mirror::Class::Status status = klass->GetStatus();
- CompilerDriver::ClassReference ref(manager->GetDexFile(), class_def_index);
+ ClassReference ref(manager->GetDexFile(), class_def_index);
CompiledClass* compiled_class = manager->GetCompiler()->GetCompiledClass(ref);
if (compiled_class == NULL) {
compiled_class = new CompiledClass(status);
@@ -2287,21 +2265,16 @@
dont_compile = false;
}
if (!dont_compile) {
- bool use_sea = false;
-
- if (Runtime::Current()->IsSeaIRMode()) {
- use_sea = true;
- }
+ CompilerFn compiler = compiler_;
+#ifdef ART_SEA_IR_MODE
+ bool use_sea = Runtime::Current()->IsSeaIRMode();
+ use_sea &&= (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
if (use_sea) {
- use_sea = (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
+ compiler = sea_ir_compiler_;
}
- if (!use_sea) {
- compiled_method = (*compiler_)(*this, code_item, access_flags, invoke_type, class_def_idx,
- method_idx, class_loader, dex_file);
- } else {
- compiled_method = (*sea_ir_compiler_)(*this, code_item, access_flags, invoke_type, class_def_idx,
- method_idx, class_loader, dex_file);
- }
+#endif
+ compiled_method = (*compiler)(*this, code_item, access_flags, invoke_type, class_def_idx,
+ method_idx, class_loader, dex_file);
CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
} else if (allow_dex_to_dex_compilation) {
// TODO: add a mode to disable DEX-to-DEX compilation ?
@@ -2365,8 +2338,7 @@
typedef void (*SetBitcodeFileNameFn)(CompilerDriver&, std::string const&);
SetBitcodeFileNameFn set_bitcode_file_name =
- FindFunction<SetBitcodeFileNameFn>(MakeCompilerSoName(compiler_backend_), compiler_library_,
- "compilerLLVMSetBitcodeFileName");
+ reinterpret_cast<SetBitcodeFileNameFn>(compilerLLVMSetBitcodeFileName);
set_bitcode_file_name(*this, filename);
}
@@ -2386,45 +2358,16 @@
bool CompilerDriver::WriteElf(const std::string& android_root,
bool is_host,
- const std::vector<const DexFile*>& dex_files,
+ const std::vector<const art::DexFile*>& dex_files,
std::vector<uint8_t>& oat_contents,
- File* file) {
- typedef bool (*WriteElfFn)(CompilerDriver&,
- const std::string& android_root,
- bool is_host,
- const std::vector<const DexFile*>& dex_files,
- std::vector<uint8_t>&,
- File*);
- WriteElfFn WriteElf =
- FindFunction<WriteElfFn>(MakeCompilerSoName(compiler_backend_), compiler_library_, "WriteElf");
- Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
- return WriteElf(*this, android_root, is_host, dex_files, oat_contents, file);
+ art::File* file)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+#if defined(ART_USE_PORTABLE_COMPILER)
+ return art::ElfWriterMclinker::Create(file, oat_contents, dex_files, android_root, is_host, *this);
+#else
+ return art::ElfWriterQuick::Create(file, oat_contents, dex_files, android_root, is_host, *this);
+#endif
}
-
-bool CompilerDriver::FixupElf(File* file, uintptr_t oat_data_begin) const {
- typedef bool (*FixupElfFn)(File*, uintptr_t oat_data_begin);
- FixupElfFn FixupElf =
- FindFunction<FixupElfFn>(MakeCompilerSoName(compiler_backend_), compiler_library_, "FixupElf");
- return FixupElf(file, oat_data_begin);
-}
-
-void CompilerDriver::GetOatElfInformation(File* file,
- size_t& oat_loaded_size,
- size_t& oat_data_offset) const {
- typedef bool (*GetOatElfInformationFn)(File*, size_t& oat_loaded_size, size_t& oat_data_offset);
- GetOatElfInformationFn GetOatElfInformation =
- FindFunction<GetOatElfInformationFn>(MakeCompilerSoName(compiler_backend_), compiler_library_,
- "GetOatElfInformation");
- GetOatElfInformation(file, oat_loaded_size, oat_data_offset);
-}
-
-bool CompilerDriver::StripElf(File* file) const {
- typedef bool (*StripElfFn)(File*);
- StripElfFn StripElf =
- FindFunction<StripElfFn>(MakeCompilerSoName(compiler_backend_), compiler_library_, "StripElf");
- return StripElf(file);
-}
-
void CompilerDriver::InstructionSetToLLVMTarget(InstructionSet instruction_set,
std::string& target_triple,
std::string& target_cpu,
diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h
index b37b74b..d37f494 100644
--- a/src/compiler/driver/compiler_driver.h
+++ b/src/compiler/driver/compiler_driver.h
@@ -22,11 +22,13 @@
#include <vector>
#include "base/mutex.h"
+#include "class_reference.h"
#include "compiled_class.h"
#include "compiled_method.h"
#include "dex_file.h"
#include "instruction_set.h"
#include "invoke_type.h"
+#include "method_reference.h"
#include "oat_file.h"
#include "runtime.h"
#include "safe_map.h"
@@ -114,30 +116,9 @@
const std::vector<uint8_t>* CreateInterpreterToQuickEntry() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // A class is uniquely located by its DexFile and the class_defs_ table index into that DexFile
- typedef std::pair<const DexFile*, uint32_t> ClassReference;
-
CompiledClass* GetCompiledClass(ClassReference ref) const
LOCKS_EXCLUDED(compiled_classes_lock_);
- // A method is uniquely located by its DexFile and the method_ids_ table index into that DexFile
- struct MethodReference {
- MethodReference(const DexFile* file, uint32_t index) : dex_file(file), dex_method_index(index) {
- }
- const DexFile* dex_file;
- uint32_t dex_method_index;
- };
-
- struct MethodReferenceComparator {
- bool operator()(MethodReference mr1, MethodReference mr2) const {
- if (mr1.dex_file == mr2.dex_file) {
- return mr1.dex_method_index < mr2.dex_method_index;
- } else {
- return mr1.dex_file < mr2.dex_file;
- }
- }
- };
-
CompiledMethod* GetCompiledMethod(MethodReference ref) const
LOCKS_EXCLUDED(compiled_methods_lock_);
@@ -212,15 +193,11 @@
}
- // TODO: remove these Elf wrappers when libart links against LLVM (when separate compiler library is gone)
bool WriteElf(const std::string& android_root,
bool is_host,
const std::vector<const DexFile*>& dex_files,
std::vector<uint8_t>& oat_contents,
File* file);
- bool FixupElf(File* file, uintptr_t oat_data_begin) const;
- void GetOatElfInformation(File* file, size_t& oat_loaded_size, size_t& oat_data_offset) const;
- bool StripElf(File* file) const;
// TODO: move to a common home for llvm helpers once quick/portable are merged
static void InstructionSetToLLVMTarget(InstructionSet instruction_set,
@@ -404,7 +381,9 @@
uint32_t class_dex_idx, uint32_t method_idx,
jobject class_loader, const DexFile& dex_file);
CompilerFn compiler_;
+#ifdef ART_SEA_IR_MODE
CompilerFn sea_ir_compiler_;
+#endif
CompilerFn dex_to_dex_compiler_;
@@ -429,16 +408,6 @@
DISALLOW_COPY_AND_ASSIGN(CompilerDriver);
};
-inline bool operator<(const CompilerDriver::ClassReference& lhs, const CompilerDriver::ClassReference& rhs) {
- if (lhs.second < rhs.second) {
- return true;
- } else if (lhs.second > rhs.second) {
- return false;
- } else {
- return (lhs.first < rhs.first);
- }
-}
-
} // namespace art
#endif // ART_SRC_COMPILER_DRIVER_COMPILER_DRIVER_H_