Rewrite the compiler interface for CompilerDriver.
Change-Id: I15fa9afe7ffb7283ebda8d788a1e02793e3f75a6
diff --git a/compiler/Android.mk b/compiler/Android.mk
index c6662c2..27bc3a3 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -90,6 +90,7 @@
utils/x86/assembler_x86.cc \
utils/x86/managed_register_x86.cc \
buffered_output_stream.cc \
+ compiler_backend.cc \
elf_fixup.cc \
elf_stripper.cc \
elf_writer.cc \
diff --git a/compiler/compiler_backend.cc b/compiler/compiler_backend.cc
new file mode 100644
index 0000000..b8f21a9
--- /dev/null
+++ b/compiler/compiler_backend.cc
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "compiler_backend.h"
+#include "elf_writer_quick.h"
+#include "dex/quick/mir_to_lir.h"
+#include "dex/mir_graph.h"
+#include "driver/compiler_driver.h"
+#include "mirror/art_method-inl.h"
+
+#ifdef ART_USE_PORTABLE_COMPILER
+#include "dex/portable/mir_to_gbc.h"
+#include "elf_writer_mclinker.h"
+#endif
+
+namespace art {
+
+#ifdef ART_SEA_IR_MODE
+extern "C" art::CompiledMethod* SeaIrCompileMethod(art::CompilerDriver& compiler,
+ const art::DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ art::InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const art::DexFile& dex_file);
+#endif
+
+extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver);
+extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& driver);
+extern "C" art::CompiledMethod* ArtQuickCompileMethod(art::CompilerDriver& compiler,
+ const art::DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ art::InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const art::DexFile& dex_file);
+
+extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver& compiler,
+ uint32_t access_flags, uint32_t method_idx,
+ const art::DexFile& dex_file);
+
+
+static CompiledMethod* TryCompileWithSeaIR(art::CompilerDriver& compiler,
+ const art::DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ art::InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const art::DexFile& dex_file) {
+#ifdef ART_SEA_IR_MODE
+ bool use_sea = Runtime::Current()->IsSeaIRMode();
+ use_sea = use_sea &&
+ (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
+ if (use_sea) {
+ LOG(INFO) << "Using SEA IR to compile..." << std::endl;
+ return SeaIrCompileMethod(compiler,
+ code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ class_loader,
+ dex_file);
+ }
+#endif
+ return nullptr;
+}
+
+
+class QuickBackend : public CompilerBackend {
+ public:
+ QuickBackend() : CompilerBackend(100) {}
+
+ void Init(CompilerDriver& driver) const {
+ ArtInitQuickCompilerContext(driver);
+ }
+
+ void UnInit(CompilerDriver& driver) const {
+ ArtUnInitQuickCompilerContext(driver);
+ }
+
+ CompiledMethod* Compile(CompilerDriver& compiler,
+ const DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const DexFile& dex_file) const {
+ CompiledMethod* method = TryCompileWithSeaIR(compiler,
+ code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ class_loader,
+ dex_file);
+ if (method != nullptr) return method;
+
+ return ArtQuickCompileMethod(compiler,
+ code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ class_loader,
+ dex_file);
+ }
+
+ CompiledMethod* JniCompile(CompilerDriver& driver,
+ uint32_t access_flags,
+ uint32_t method_idx,
+ const DexFile& dex_file) const {
+ return ArtQuickJniCompileMethod(driver, access_flags, method_idx, dex_file);
+ }
+
+ uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
+ return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
+ }
+
+ bool WriteElf(art::File* file,
+ OatWriter& oat_writer,
+ const std::vector<const art::DexFile*>& dex_files,
+ const std::string& android_root,
+ bool is_host, const CompilerDriver& driver) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host, driver);
+ }
+
+ Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
+ Mir2Lir* mir_to_lir = nullptr;
+ switch (cu->instruction_set) {
+ case kThumb2:
+ mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+ break;
+ case kMips:
+ mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+ break;
+ case kX86:
+ mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
+ break;
+ default:
+ LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
+ }
+
+ /* The number of compiler temporaries depends on backend so set it up now if possible */
+ if (mir_to_lir) {
+ size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps();
+ bool set_max = cu->mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps);
+ CHECK(set_max);
+ }
+ return mir_to_lir;;
+ }
+
+ void InitCompilationUnit(CompilationUnit& cu) const {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuickBackend);
+};
+
+#ifdef ART_USE_PORTABLE_COMPILER
+
+extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver);
+extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
+extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
+ const art::DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ art::InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const art::DexFile& dex_file);
+extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
+ uint32_t access_flags, uint32_t method_idx,
+ const art::DexFile& dex_file);
+
+
+class LLVMBackend : public CompilerBackend {
+ public:
+ LLVMBackend() : CompilerBackend(1000) {}
+
+ void Init(CompilerDriver& driver) const {
+ ArtInitCompilerContext(driver);
+ }
+
+ void UnInit(CompilerDriver& driver) const {
+ ArtUnInitCompilerContext(driver);
+ }
+
+ CompiledMethod* Compile(CompilerDriver& compiler,
+ const DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const DexFile& dex_file) const {
+ CompiledMethod* method = TryCompileWithSeaIR(compiler,
+ code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ class_loader,
+ dex_file);
+ if (method != nullptr) return method;
+
+ return ArtCompileMethod(compiler,
+ code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ class_loader,
+ dex_file);
+ }
+
+ CompiledMethod* JniCompile(CompilerDriver& driver,
+ uint32_t access_flags,
+ uint32_t method_idx,
+ const DexFile& dex_file) const {
+ return ArtLLVMJniCompileMethod(driver, access_flags, method_idx, dex_file);
+ }
+
+ uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
+ return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
+ }
+
+ bool WriteElf(art::File* file,
+ OatWriter& oat_writer,
+ const std::vector<const art::DexFile*>& dex_files,
+ const std::string& android_root,
+ bool is_host, const CompilerDriver& driver) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return art::ElfWriterMclinker::Create(
+ file, oat_writer, dex_files, android_root, is_host, driver);
+ }
+
+ Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
+ return PortableCodeGenerator(
+ cu, cu->mir_graph.get(), &cu->arena,
+ reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
+ }
+
+ void InitCompilationUnit(CompilationUnit& cu) const {
+ // Fused long branches not currently useful in bitcode.
+ cu.disable_opt |=
+ (1 << kBranchFusing) |
+ (1 << kSuppressExceptionEdges);
+ }
+
+ bool isPortable() const { return true; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LLVMBackend);
+};
+#endif
+
+CompilerBackend* CompilerBackend::Create(CompilerBackend::Kind kind) {
+ switch (kind) {
+ case kQuick:
+ return new QuickBackend();
+ break;
+ case kPortable:
+#ifdef ART_USE_PORTABLE_COMPILER
+ return new LLVMBackend();
+#else
+ LOG(FATAL) << "Portable compiler not compiled";
+#endif
+ break;
+ default:
+ LOG(FATAL) << "UNREACHABLE";
+ }
+ return nullptr;
+}
+
+} // namespace art
diff --git a/compiler/compiler_backend.h b/compiler/compiler_backend.h
new file mode 100644
index 0000000..5ebeef1
--- /dev/null
+++ b/compiler/compiler_backend.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 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_COMPILER_COMPILER_BACKEND_H_
+#define ART_COMPILER_COMPILER_BACKEND_H_
+
+#include "dex_file.h"
+#include "os.h"
+
+namespace art {
+
+class Backend;
+class CompilationUnit;
+class CompilerDriver;
+class CompiledMethod;
+class MIRGraph;
+class OatWriter;
+
+namespace mirror {
+ class ArtMethod;
+}
+
+class CompilerBackend {
+ public:
+ enum Kind {
+ kQuick,
+ kPortable
+ };
+
+ CompilerBackend(int warning)
+ : maximum_compilation_time_before_warning_(warning) {}
+
+ static CompilerBackend* Create(Kind kind);
+
+ virtual void Init(CompilerDriver& driver) const = 0;
+
+ virtual void UnInit(CompilerDriver& driver) const = 0;
+
+ virtual CompiledMethod* Compile(CompilerDriver& compiler,
+ const DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const DexFile& dex_file) const = 0;
+
+ virtual CompiledMethod* JniCompile(CompilerDriver& driver,
+ uint32_t access_flags,
+ uint32_t method_idx,
+ const DexFile& dex_file) const = 0;
+
+ virtual uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const = 0;
+
+ virtual bool WriteElf(art::File* file,
+ OatWriter& oat_writer,
+ const std::vector<const art::DexFile*>& dex_files,
+ const std::string& android_root,
+ bool is_host, const CompilerDriver& driver) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
+
+ virtual Backend* GetCodeGenerator(CompilationUnit* cu,
+ void* compilation_unit) const = 0;
+
+ uint64_t GetMaximumCompilationTimeBeforeWarning() const {
+ return maximum_compilation_time_before_warning_;
+ }
+
+ virtual bool IsPortable() const { return false; }
+
+ virtual void InitCompilationUnit(CompilationUnit& cu) const = 0;
+
+ virtual ~CompilerBackend() {}
+
+ private:
+ uint64_t maximum_compilation_time_before_warning_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompilerBackend);
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_DRIVER_COMPILER_BACKEND_H_
diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h
index 32fd79b..ea8eb1c 100644
--- a/compiler/dex/compiler_ir.h
+++ b/compiler/dex/compiler_ir.h
@@ -68,7 +68,7 @@
uint32_t disable_opt; // opt_control_vector flags.
uint32_t enable_debug; // debugControlVector flags.
bool verbose;
- CompilerBackend compiler_backend;
+ const CompilerBackend* compiler_backend;
InstructionSet instruction_set;
const InstructionSetFeatures& GetInstructionSetFeatures() {
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 8f83cd0..591d92a 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#include <llvm/Support/Threading.h>
-
+#include "compiler_backend.h"
#include "compiler_internals.h"
#include "driver/compiler_driver.h"
#include "dataflow_iterator-inl.h"
@@ -27,42 +26,9 @@
#include "base/logging.h"
#include "base/timing_logger.h"
-#if defined(ART_USE_PORTABLE_COMPILER)
-#include "dex/portable/mir_to_gbc.h"
-#include "llvm/llvm_compilation_unit.h"
-#endif
-
#include "dex/quick/dex_file_to_method_inliner_map.h"
-namespace {
-#if !defined(ART_USE_PORTABLE_COMPILER)
- pthread_once_t llvm_multi_init = PTHREAD_ONCE_INIT;
-#endif
- void InitializeLLVMForQuick() {
- ::llvm::llvm_start_multithreaded();
- }
-}
-
namespace art {
-namespace llvm {
-::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);
-}
-
-LLVMInfo::LLVMInfo() {
-#if !defined(ART_USE_PORTABLE_COMPILER)
- pthread_once(&llvm_multi_init, InitializeLLVMForQuick);
-#endif
- // Create context, module, intrinsic helper & ir builder
- llvm_context_.reset(new ::llvm::LLVMContext());
- llvm_module_ = new ::llvm::Module("art", *llvm_context_);
- ::llvm::StructType::create(*llvm_context_, "JavaObject");
- art::llvm::makeLLVMModuleContents(llvm_module_);
- intrinsic_helper_.reset(new art::llvm::IntrinsicHelper(*llvm_context_, *llvm_module_));
- ir_builder_.reset(new art::llvm::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
-}
-
-LLVMInfo::~LLVMInfo() {
-}
extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver) {
CHECK(driver.GetCompilerContext() == NULL);
@@ -123,7 +89,7 @@
disable_opt(0),
enable_debug(0),
verbose(false),
- compiler_backend(kNoBackend),
+ compiler_backend(NULL),
instruction_set(kNone),
num_dalvik_registers(0),
insns(NULL),
@@ -163,15 +129,12 @@
}
static CompiledMethod* CompileMethod(CompilerDriver& compiler,
- const CompilerBackend compiler_backend,
+ CompilerBackend* compiler_backend,
const DexFile::CodeItem* code_item,
uint32_t access_flags, InvokeType invoke_type,
uint16_t class_def_idx, uint32_t method_idx,
- jobject class_loader, const DexFile& dex_file
-#if defined(ART_USE_PORTABLE_COMPILER)
- , llvm::LlvmCompilationUnit* llvm_compilation_unit
-#endif
-) {
+ jobject class_loader, const DexFile& dex_file,
+ void* llvm_compilation_unit) {
VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
if (code_item->insns_size_in_code_units_ >= 0x10000) {
LOG(INFO) << "Method size exceeds compiler limits: " << code_item->insns_size_in_code_units_
@@ -211,12 +174,7 @@
* MIR and backend flags? Need command-line setting as well.
*/
- if (compiler_backend == kPortable) {
- // Fused long branches not currently useful in bitcode.
- cu.disable_opt |=
- (1 << kBranchFusing) |
- (1 << kSuppressExceptionEdges);
- }
+ compiler_backend->InitCompilationUnit(cu);
if (cu.instruction_set == kMips) {
// Disable some optimizations for mips for now
@@ -241,37 +199,7 @@
* The reason we do this is that optimizations on the MIR graph may need to get information
* that is only available if a CG exists.
*/
-#if defined(ART_USE_PORTABLE_COMPILER)
- if (compiler_backend == kPortable) {
- cu.cg.reset(PortableCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena, llvm_compilation_unit));
- } else {
-#endif
- Mir2Lir* mir_to_lir = nullptr;
- switch (compiler.GetInstructionSet()) {
- case kThumb2:
- mir_to_lir = ArmCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena);
- break;
- case kMips:
- mir_to_lir = MipsCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena);
- break;
- case kX86:
- mir_to_lir = X86CodeGenerator(&cu, cu.mir_graph.get(), &cu.arena);
- break;
- default:
- LOG(FATAL) << "Unexpected instruction set: " << compiler.GetInstructionSet();
- }
-
- cu.cg.reset(mir_to_lir);
-
- /* The number of compiler temporaries depends on backend so set it up now if possible */
- if (mir_to_lir) {
- size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps();
- bool set_max = cu.mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps);
- CHECK(set_max);
- }
-#if defined(ART_USE_PORTABLE_COMPILER)
- }
-#endif
+ cu.cg.reset(compiler_backend->GetCodeGenerator(&cu, llvm_compilation_unit));
/* Gathering opcode stats? */
if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
@@ -283,11 +211,9 @@
class_loader, dex_file);
cu.NewTimingSplit("MIROpt:CheckFilters");
-#if !defined(ART_USE_PORTABLE_COMPILER)
if (cu.mir_graph->SkipCompilation(Runtime::Current()->GetCompilerFilter())) {
return NULL;
}
-#endif
/* Create the pass driver and launch it */
PassDriver driver(&cu);
@@ -338,7 +264,7 @@
}
CompiledMethod* CompileOneMethod(CompilerDriver& compiler,
- const CompilerBackend backend,
+ CompilerBackend* backend,
const DexFile::CodeItem* code_item,
uint32_t access_flags,
InvokeType invoke_type,
@@ -346,13 +272,9 @@
uint32_t method_idx,
jobject class_loader,
const DexFile& dex_file,
- llvm::LlvmCompilationUnit* llvm_compilation_unit) {
+ void* compilation_unit) {
return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, class_def_idx,
- method_idx, class_loader, dex_file
-#if defined(ART_USE_PORTABLE_COMPILER)
- , llvm_compilation_unit
-#endif
- ); // NOLINT(whitespace/parens)
+ method_idx, class_loader, dex_file, compilation_unit);
}
} // namespace art
@@ -364,7 +286,7 @@
uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
const art::DexFile& dex_file) {
// TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default
- art::CompilerBackend backend = compiler.GetCompilerBackend();
+ art::CompilerBackend* backend = compiler.GetCompilerBackend();
return art::CompileOneMethod(compiler, backend, code_item, access_flags, invoke_type,
class_def_idx, method_idx, class_loader, dex_file,
NULL /* use thread llvm_info */);
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 209ed3d..b91ef28 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -406,7 +406,7 @@
// Is this the select pattern?
// TODO: flesh out support for Mips. NOTE: llvm's select op doesn't quite work here.
// TUNING: expand to support IF_xx compare & branches
- if ((cu_->compiler_backend != kPortable) &&
+ if (cu_->compiler_backend->IsPortable() &&
(cu_->instruction_set == kThumb2 || cu_->instruction_set == kX86) &&
((mir->dalvikInsn.opcode == Instruction::IF_EQZ) ||
(mir->dalvikInsn.opcode == Instruction::IF_NEZ))) {
diff --git a/compiler/dex/portable/mir_to_gbc.cc b/compiler/dex/portable/mir_to_gbc.cc
index e6cc2de..3187fbb 100644
--- a/compiler/dex/portable/mir_to_gbc.cc
+++ b/compiler/dex/portable/mir_to_gbc.cc
@@ -41,6 +41,22 @@
const char kCatchBlock = 'C';
namespace art {
+namespace llvm {
+::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);
+}
+
+LLVMInfo::LLVMInfo() {
+ // Create context, module, intrinsic helper & ir builder
+ llvm_context_.reset(new ::llvm::LLVMContext());
+ llvm_module_ = new ::llvm::Module("art", *llvm_context_);
+ ::llvm::StructType::create(*llvm_context_, "JavaObject");
+ art::llvm::makeLLVMModuleContents(llvm_module_);
+ intrinsic_helper_.reset(new art::llvm::IntrinsicHelper(*llvm_context_, *llvm_module_));
+ ir_builder_.reset(new art::llvm::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
+}
+
+LLVMInfo::~LLVMInfo() {
+}
::llvm::BasicBlock* MirConverter::GetLLVMBlock(int id) {
return id_to_block_map_.Get(id);
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 5b22817..8bf2f42 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -25,6 +25,7 @@
#include "base/stl_util.h"
#include "base/timing_logger.h"
#include "class_linker.h"
+#include "compiler_backend.h"
#include "dex_compilation_unit.h"
#include "dex_file-inl.h"
#include "dex/verification_results.h"
@@ -52,12 +53,6 @@
#include "verifier/method_verifier.h"
#include "verifier/method_verifier-inl.h"
-#if defined(ART_USE_PORTABLE_COMPILER)
-#include "elf_writer_mclinker.h"
-#else
-#include "elf_writer_quick.h"
-#endif
-
namespace art {
static double Percentage(size_t x, size_t y) {
@@ -287,28 +282,6 @@
DISALLOW_COPY_AND_ASSIGN(AOTCompilationStats);
};
-extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver);
-extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver);
-
-extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
-extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& driver);
-
-extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
- const art::DexFile::CodeItem* code_item,
- uint32_t access_flags,
- art::InvokeType invoke_type,
- uint16_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,
- uint16_t class_def_idx,
- uint32_t method_idx,
- jobject class_loader,
- const art::DexFile& dex_file);
extern "C" art::CompiledMethod* ArtCompileDEX(art::CompilerDriver& compiler,
const art::DexFile::CodeItem* code_item,
@@ -318,36 +291,20 @@
uint32_t method_idx,
jobject class_loader,
const art::DexFile& dex_file);
-#ifdef ART_SEA_IR_MODE
-extern "C" art::CompiledMethod* SeaIrCompileMethod(art::CompilerDriver& compiler,
- const art::DexFile::CodeItem* code_item,
- uint32_t access_flags,
- art::InvokeType invoke_type,
- uint16_t class_def_idx,
- uint32_t method_idx,
- jobject class_loader,
- const art::DexFile& dex_file);
-#endif
-extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
- uint32_t access_flags, uint32_t method_idx,
- const art::DexFile& dex_file);
-
-extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver& compiler,
- uint32_t access_flags, uint32_t method_idx,
- const art::DexFile& dex_file);
extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver& driver,
std::string const& filename);
CompilerDriver::CompilerDriver(VerificationResults* verification_results,
DexFileToMethodInlinerMap* method_inliner_map,
- CompilerBackend compiler_backend, InstructionSet instruction_set,
+ CompilerBackend::Kind compiler_backend_kind,
+ InstructionSet instruction_set,
InstructionSetFeatures instruction_set_features,
bool image, DescriptorSet* image_classes, size_t thread_count,
bool dump_stats, bool dump_passes, CumulativeLogger* timer)
: verification_results_(verification_results),
method_inliner_map_(method_inliner_map),
- compiler_backend_(compiler_backend),
+ compiler_backend_(CompilerBackend::Create(compiler_backend_kind)),
instruction_set_(instruction_set),
instruction_set_features_(instruction_set_features),
freezing_constructor_lock_("freezing constructor lock"),
@@ -362,9 +319,7 @@
dump_passes_(dump_passes),
timings_logger_(timer),
compiler_library_(NULL),
- compiler_(NULL),
compiler_context_(NULL),
- jni_compiler_(NULL),
compiler_enable_auto_elf_loading_(NULL),
compiler_get_method_code_addr_(NULL),
support_boot_image_fixup_(instruction_set != kMips),
@@ -375,34 +330,9 @@
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
- typedef void (*InitCompilerContextFn)(CompilerDriver&);
- InitCompilerContextFn init_compiler_context;
- if (compiler_backend_ == kPortable) {
- // Initialize compiler_context_
- init_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtInitCompilerContext);
- compiler_ = reinterpret_cast<CompilerFn>(ArtCompileMethod);
- } else {
- init_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtInitQuickCompilerContext);
- compiler_ = reinterpret_cast<CompilerFn>(ArtQuickCompileMethod);
- }
-
dex_to_dex_compiler_ = reinterpret_cast<DexToDexCompilerFn>(ArtCompileDEX);
-#ifdef ART_SEA_IR_MODE
- sea_ir_compiler_ = NULL;
- if (Runtime::Current()->IsSeaIRMode()) {
- sea_ir_compiler_ = reinterpret_cast<CompilerFn>(SeaIrCompileMethod);
- }
-#endif
-
- init_compiler_context(*this);
-
- if (compiler_backend_ == kPortable) {
- jni_compiler_ = reinterpret_cast<JniCompilerFn>(ArtLLVMJniCompileMethod);
- } else {
- jni_compiler_ = reinterpret_cast<JniCompilerFn>(ArtQuickJniCompileMethod);
- }
+ compiler_backend_->Init(*this);
CHECK(!Runtime::Current()->IsStarted());
if (!image_) {
@@ -449,16 +379,7 @@
STLDeleteElements(&classes_to_patch_);
}
CHECK_PTHREAD_CALL(pthread_key_delete, (tls_key_), "delete tls key");
- typedef void (*UninitCompilerContextFn)(CompilerDriver&);
- UninitCompilerContextFn uninit_compiler_context;
- // Uninitialize compiler_context_
- // TODO: rework to combine initialization/uninitialization
- if (compiler_backend_ == kPortable) {
- uninit_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtUnInitCompilerContext);
- } else {
- uninit_compiler_context = reinterpret_cast<void (*)(CompilerDriver&)>(ArtUnInitQuickCompilerContext);
- }
- uninit_compiler_context(*this);
+ compiler_backend_->UnInit(*this);
}
CompilerTls* CompilerDriver::GetTls() {
@@ -1153,7 +1074,7 @@
*direct_method = 0;
bool use_dex_cache = false;
const bool compiling_boot = Runtime::Current()->GetHeap()->IsCompilingBoot();
- if (compiler_backend_ == kPortable) {
+ if (compiler_backend_->IsPortable()) {
if (sharp_type != kStatic && sharp_type != kDirect) {
return;
}
@@ -1230,23 +1151,13 @@
CHECK(!method->IsAbstract());
*type = sharp_type;
*direct_method = reinterpret_cast<uintptr_t>(method);
- if (compiler_backend_ == kQuick) {
- *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
- } else {
- CHECK_EQ(compiler_backend_, kPortable);
- *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
- }
+ *direct_code = compiler_backend_->GetEntryPointOf(method);
target_method->dex_file = method->GetDeclaringClass()->GetDexCache()->GetDexFile();
target_method->dex_method_index = method->GetDexMethodIndex();
} else if (!must_use_direct_pointers) {
// Set the code and rely on the dex cache for the method.
*type = sharp_type;
- if (compiler_backend_ == kQuick) {
- *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
- } else {
- CHECK_EQ(compiler_backend_, kPortable);
- *direct_code = reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
- }
+ *direct_code = compiler_backend_->GetEntryPointOf(method);
} else {
// Direct pointers were required but none were available.
VLOG(compiler) << "Dex cache devirtualization failed for: " << PrettyMethod(method);
@@ -2417,7 +2328,7 @@
uint64_t start_ns = NanoTime();
if ((access_flags & kAccNative) != 0) {
- compiled_method = (*jni_compiler_)(*this, access_flags, method_idx, dex_file);
+ compiled_method = compiler_backend_->JniCompile(*this, access_flags, method_idx, dex_file);
CHECK(compiled_method != NULL);
} else if ((access_flags & kAccAbstract) != 0) {
} else {
@@ -2425,19 +2336,10 @@
bool compile = VerificationResults::IsCandidateForCompilation(method_ref, access_flags);
if (compile) {
- CompilerFn compiler = compiler_;
-#ifdef ART_SEA_IR_MODE
- bool use_sea = Runtime::Current()->IsSeaIRMode();
- use_sea = use_sea &&
- (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
- if (use_sea) {
- compiler = sea_ir_compiler_;
- LOG(INFO) << "Using SEA IR to compile..." << std::endl;
- }
-#endif
// NOTE: if compiler declines to compile this method, it will return NULL.
- compiled_method = (*compiler)(*this, code_item, access_flags, invoke_type, class_def_idx,
- method_idx, class_loader, dex_file);
+ compiled_method = compiler_backend_->Compile(
+ *this, code_item, access_flags, invoke_type, class_def_idx,
+ method_idx, class_loader, dex_file);
} else if (dex_to_dex_compilation_level != kDontDexToDexCompile) {
// TODO: add a mode to disable DEX-to-DEX compilation ?
(*dex_to_dex_compiler_)(*this, code_item, access_flags,
@@ -2447,12 +2349,7 @@
}
}
uint64_t duration_ns = NanoTime() - start_ns;
-#ifdef ART_USE_PORTABLE_COMPILER
- const uint64_t kWarnMilliSeconds = 1000;
-#else
- const uint64_t kWarnMilliSeconds = 100;
-#endif
- if (duration_ns > MsToNs(kWarnMilliSeconds)) {
+ if (duration_ns > MsToNs(compiler_backend_->GetMaximumCompilationTimeBeforeWarning())) {
LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
<< " took " << PrettyDuration(duration_ns);
}
@@ -2549,11 +2446,7 @@
OatWriter& oat_writer,
art::File* file)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-#if defined(ART_USE_PORTABLE_COMPILER)
- return art::ElfWriterMclinker::Create(file, oat_writer, dex_files, android_root, is_host, *this);
-#else
- return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host, *this);
-#endif
+ return compiler_backend_->WriteElf(file, oat_writer, dex_files, android_root, is_host, *this);
}
void CompilerDriver::InstructionSetToLLVMTarget(InstructionSet instruction_set,
std::string& target_triple,
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index c4ac9db..a9e029d 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -26,6 +26,7 @@
#include "class_reference.h"
#include "compiled_class.h"
#include "compiled_method.h"
+#include "compiler_backend.h"
#include "dex_file.h"
#include "dex/arena_allocator.h"
#include "instruction_set.h"
@@ -44,21 +45,15 @@
} // namespace verifier
class AOTCompilationStats;
-class ParallelCompilationManager;
class DexCompilationUnit;
class DexFileToMethodInlinerMap;
class InlineIGetIPutData;
class OatWriter;
+class ParallelCompilationManager;
class TimingLogger;
class VerificationResults;
class VerifiedMethod;
-enum CompilerBackend {
- kQuick,
- kPortable,
- kNoBackend
-};
-
enum EntryPointCallingConvention {
// ABI of invocations to a method's interpreter entry point.
kInterpreterAbi,
@@ -101,7 +96,8 @@
// classes.
explicit CompilerDriver(VerificationResults* verification_results,
DexFileToMethodInlinerMap* method_inliner_map,
- CompilerBackend compiler_backend, InstructionSet instruction_set,
+ CompilerBackend::Kind compiler_backend_kind,
+ InstructionSet instruction_set,
InstructionSetFeatures instruction_set_features,
bool image, DescriptorSet* image_classes,
size_t thread_count, bool dump_stats, bool dump_passes,
@@ -133,8 +129,8 @@
return instruction_set_features_;
}
- CompilerBackend GetCompilerBackend() const {
- return compiler_backend_;
+ CompilerBackend* GetCompilerBackend() const {
+ return compiler_backend_.get();
}
// Are we compiling and creating an image file?
@@ -560,7 +556,7 @@
VerificationResults* verification_results_;
DexFileToMethodInlinerMap* method_inliner_map_;
- CompilerBackend compiler_backend_;
+ UniquePtr<CompilerBackend> compiler_backend_;
const InstructionSet instruction_set_;
const InstructionSetFeatures instruction_set_features_;
@@ -601,32 +597,16 @@
void* compiler_library_;
- typedef CompiledMethod* (*CompilerFn)(CompilerDriver& driver,
- const DexFile::CodeItem* code_item,
- uint32_t access_flags, InvokeType invoke_type,
- uint32_t class_dex_idx, uint32_t method_idx,
- jobject class_loader, const DexFile& dex_file);
-
typedef void (*DexToDexCompilerFn)(CompilerDriver& driver,
const DexFile::CodeItem* code_item,
uint32_t access_flags, InvokeType invoke_type,
uint32_t class_dex_idx, uint32_t method_idx,
jobject class_loader, const DexFile& dex_file,
DexToDexCompilationLevel dex_to_dex_compilation_level);
- CompilerFn compiler_;
-#ifdef ART_SEA_IR_MODE
- CompilerFn sea_ir_compiler_;
-#endif
-
DexToDexCompilerFn dex_to_dex_compiler_;
void* compiler_context_;
- typedef CompiledMethod* (*JniCompilerFn)(CompilerDriver& driver,
- uint32_t access_flags, uint32_t method_idx,
- const DexFile& dex_file);
- JniCompilerFn jni_compiler_;
-
pthread_key_t tls_key_;
// Arena pool used by the compiler.
diff --git a/compiler/llvm/compiler_llvm.cc b/compiler/llvm/compiler_llvm.cc
index 6563eb5..a5acd2a 100644
--- a/compiler/llvm/compiler_llvm.cc
+++ b/compiler/llvm/compiler_llvm.cc
@@ -39,12 +39,12 @@
namespace art {
void CompileOneMethod(CompilerDriver& driver,
- const CompilerBackend compilerBackend,
+ CompilerBackend* compilerBackend,
const DexFile::CodeItem* code_item,
uint32_t access_flags, InvokeType invoke_type,
uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
const DexFile& dex_file,
- llvm::LlvmCompilationUnit* llvm_info);
+ void* llvm_info);
}
namespace llvm {
@@ -142,7 +142,7 @@
cunit->SetCompilerDriver(compiler_driver_);
// TODO: consolidate ArtCompileMethods
CompileOneMethod(*compiler_driver_,
- kPortable,
+ compiler_driver_->GetCompilerBackend(),
dex_compilation_unit->GetCodeItem(),
dex_compilation_unit->GetAccessFlags(),
invoke_type,
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index f6b511c..10d2c5c 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -15,6 +15,7 @@
*/
#include "compiler/oat_writer.h"
+#include "compiler/compiler_backend.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object_array-inl.h"
@@ -84,12 +85,14 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
// TODO: make selectable.
- CompilerBackend compiler_backend = kUsePortableCompiler ? kPortable : kQuick;
+ CompilerBackend::Kind compiler_backend = kUsePortableCompiler
+ ? CompilerBackend::kPortable
+ : CompilerBackend::kQuick;
InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
InstructionSetFeatures insn_features;
verification_results_.reset(new VerificationResults);
- method_inliner_map_.reset(compiler_backend == kQuick ? new DexFileToMethodInlinerMap : nullptr);
+ method_inliner_map_.reset(new DexFileToMethodInlinerMap);
callbacks_.Reset(verification_results_.get(), method_inliner_map_.get());
timer_.reset(new CumulativeLogger("Compilation times"));
compiler_driver_.reset(new CompilerDriver(verification_results_.get(),
diff --git a/compiler/sea_ir/frontend.cc b/compiler/sea_ir/frontend.cc
index 6c779c8..b57007b 100644
--- a/compiler/sea_ir/frontend.cc
+++ b/compiler/sea_ir/frontend.cc
@@ -38,15 +38,12 @@
namespace art {
static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler,
- const CompilerBackend compiler_backend,
+ CompilerBackend* compiler_backend,
const DexFile::CodeItem* code_item,
uint32_t method_access_flags, InvokeType invoke_type,
uint16_t class_def_idx, uint32_t method_idx,
- jobject class_loader, const DexFile& dex_file
-#if defined(ART_USE_PORTABLE_COMPILER)
- , llvm::LlvmCompilationUnit* llvm_compilation_unit
-#endif
-) {
+ jobject class_loader, const DexFile& dex_file,
+ void* llvm_compilation_unit) {
LOG(INFO) << "Compiling " << PrettyMethod(method_idx, dex_file) << ".";
sea_ir::SeaGraph* ir_graph = sea_ir::SeaGraph::GetGraph(dex_file);
std::string symbol = "dex_" + MangleForJni(PrettyMethod(method_idx, dex_file));
@@ -65,7 +62,7 @@
}
CompiledMethod* SeaIrCompileOneMethod(CompilerDriver& compiler,
- const CompilerBackend backend,
+ CompilerBackend* backend,
const DexFile::CodeItem* code_item,
uint32_t method_access_flags,
InvokeType invoke_type,
@@ -73,13 +70,9 @@
uint32_t method_idx,
jobject class_loader,
const DexFile& dex_file,
- llvm::LlvmCompilationUnit* llvm_compilation_unit) {
+ void* llvm_compilation_unit) {
return CompileMethodWithSeaIr(compiler, backend, code_item, method_access_flags, invoke_type,
- class_def_idx, method_idx, class_loader, dex_file
-#if defined(ART_USE_PORTABLE_COMPILER)
- , llvm_compilation_unit
-#endif
- ); // NOLINT
+ class_def_idx, method_idx, class_loader, dex_file, llvm_compilation_unit);
}
extern "C" art::CompiledMethod*
@@ -90,7 +83,7 @@
const art::DexFile& dex_file) {
// TODO: Check method fingerprint here to determine appropriate backend type.
// Until then, use build default
- art::CompilerBackend backend = compiler.GetCompilerBackend();
+ art::CompilerBackend* backend = compiler.GetCompilerBackend();
return art::SeaIrCompileOneMethod(compiler, backend, code_item, method_access_flags, invoke_type,
class_def_idx, method_idx, class_loader, dex_file,
NULL /* use thread llvm_info */);