diff options
author | Brian Carlstrom <bdc@google.com> | 2013-07-12 13:46:57 -0700 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2013-07-12 17:49:01 -0700 |
commit | 7940e44f4517de5e2634a7e07d58d0fb26160513 (patch) | |
tree | ac90242d96229a6942f6e24ab137bc1f8f2e0025 /compiler/dex/frontend.cc | |
parent | 5cd9e3b122f276f610980cbaf0d2ad6ed4cd9088 (diff) | |
download | art-7940e44f4517de5e2634a7e07d58d0fb26160513.tar.gz art-7940e44f4517de5e2634a7e07d58d0fb26160513.tar.bz2 art-7940e44f4517de5e2634a7e07d58d0fb26160513.zip |
Create separate Android.mk for main build targets
The runtime, compiler, dex2oat, and oatdump now are in seperate trees
to prevent dependency creep. They can now be individually built
without rebuilding the rest of the art projects. dalvikvm and jdwpspy
were already this way. Builds in the art directory should behave as
before, building everything including tests.
Change-Id: Ic6b1151e5ed0f823c3dd301afd2b13eb2d8feb81
Diffstat (limited to 'compiler/dex/frontend.cc')
-rw-r--r-- | compiler/dex/frontend.cc | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc new file mode 100644 index 000000000..746d475a9 --- /dev/null +++ b/compiler/dex/frontend.cc @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2011 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 <llvm/Support/Threading.h> + +#include "compiler_internals.h" +#include "driver/compiler_driver.h" +#include "dataflow_iterator-inl.h" +#include "leb128.h" +#include "mirror/object.h" +#include "runtime.h" +#include "backend.h" +#include "base/logging.h" + +#if defined(ART_USE_PORTABLE_COMPILER) +#include "dex/portable/mir_to_gbc.h" +#include "llvm/llvm_compilation_unit.h" +#endif + +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& compiler) { + CHECK(compiler.GetCompilerContext() == NULL); + LLVMInfo* llvm_info = new LLVMInfo(); + compiler.SetCompilerContext(llvm_info); +} + +extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& compiler) { + delete reinterpret_cast<LLVMInfo*>(compiler.GetCompilerContext()); + compiler.SetCompilerContext(NULL); +} + +/* Default optimizer/debug setting for the compiler. */ +static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations + (1 << kLoadStoreElimination) | + //(1 << kLoadHoisting) | + //(1 << kSuppressLoads) | + //(1 << kNullCheckElimination) | + //(1 << kPromoteRegs) | + //(1 << kTrackLiveTemps) | + //(1 << kSafeOptimizations) | + //(1 << kBBOpt) | + //(1 << kMatch) | + //(1 << kPromoteCompilerTemps) | + 0; + +static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes + //(1 << kDebugDisplayMissingTargets) | + //(1 << kDebugVerbose) | + //(1 << kDebugDumpCFG) | + //(1 << kDebugSlowFieldPath) | + //(1 << kDebugSlowInvokePath) | + //(1 << kDebugSlowStringPath) | + //(1 << kDebugSlowestFieldPath) | + //(1 << kDebugSlowestStringPath) | + //(1 << kDebugExerciseResolveMethod) | + //(1 << kDebugVerifyDataflow) | + //(1 << kDebugShowMemoryUsage) | + //(1 << kDebugShowNops) | + //(1 << kDebugCountOpcodes) | + //(1 << kDebugDumpCheckStats) | + //(1 << kDebugDumpBitcodeFile) | + //(1 << kDebugVerifyBitcode) | + //(1 << kDebugShowSummaryMemoryUsage) | + 0; + +static CompiledMethod* CompileMethod(CompilerDriver& compiler, + const CompilerBackend compiler_backend, + const DexFile::CodeItem* code_item, + uint32_t access_flags, InvokeType invoke_type, + uint32_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 +) { + VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "..."; + + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + UniquePtr<CompilationUnit> cu(new CompilationUnit); + + cu->compiler_driver = &compiler; + cu->class_linker = class_linker; + cu->instruction_set = compiler.GetInstructionSet(); + cu->compiler_backend = compiler_backend; + DCHECK((cu->instruction_set == kThumb2) || + (cu->instruction_set == kX86) || + (cu->instruction_set == kMips)); + + + /* Adjust this value accordingly once inlining is performed */ + cu->num_dalvik_registers = code_item->registers_size_; + // TODO: set this from command line + cu->compiler_flip_match = false; + bool use_match = !cu->compiler_method_match.empty(); + bool match = use_match && (cu->compiler_flip_match ^ + (PrettyMethod(method_idx, dex_file).find(cu->compiler_method_match) != + std::string::npos)); + if (!use_match || match) { + cu->disable_opt = kCompilerOptimizerDisableFlags; + cu->enable_debug = kCompilerDebugFlags; + cu->verbose = VLOG_IS_ON(compiler) || + (cu->enable_debug & (1 << kDebugVerbose)); + } + + /* + * TODO: rework handling of optimization and debug flags. Should we split out + * MIR and backend flags? Need command-line setting as well. + */ + + if (compiler_backend == kPortable) { + // Fused long branches not currently usseful in bitcode. + cu->disable_opt |= (1 << kBranchFusing); + } + + if (cu->instruction_set == kMips) { + // Disable some optimizations for mips for now + cu->disable_opt |= ( + (1 << kLoadStoreElimination) | + (1 << kLoadHoisting) | + (1 << kSuppressLoads) | + (1 << kNullCheckElimination) | + (1 << kPromoteRegs) | + (1 << kTrackLiveTemps) | + (1 << kSafeOptimizations) | + (1 << kBBOpt) | + (1 << kMatch) | + (1 << kPromoteCompilerTemps)); + } + + cu->mir_graph.reset(new MIRGraph(cu.get(), &cu->arena)); + + /* Gathering opcode stats? */ + if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { + cu->mir_graph->EnableOpcodeCounting(); + } + + /* Build the raw MIR graph */ + cu->mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, + class_loader, dex_file); + + /* Do a code layout pass */ + cu->mir_graph->CodeLayout(); + + /* Perform SSA transformation for the whole method */ + cu->mir_graph->SSATransformation(); + + /* Do constant propagation */ + cu->mir_graph->PropagateConstants(); + + /* Count uses */ + cu->mir_graph->MethodUseCount(); + + /* Perform null check elimination */ + cu->mir_graph->NullCheckElimination(); + + /* Combine basic blocks where possible */ + cu->mir_graph->BasicBlockCombine(); + + /* Do some basic block optimizations */ + cu->mir_graph->BasicBlockOptimization(); + + if (cu->enable_debug & (1 << kDebugDumpCheckStats)) { + cu->mir_graph->DumpCheckStats(); + } + + if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { + cu->mir_graph->ShowOpcodeStats(); + } + + /* Set up regLocation[] array to describe values - one for each ssa_name. */ + cu->mir_graph->BuildRegLocations(); + + CompiledMethod* result = NULL; + +#if defined(ART_USE_PORTABLE_COMPILER) + if (compiler_backend == kPortable) { + cu->cg.reset(PortableCodeGenerator(cu.get(), cu->mir_graph.get(), &cu->arena, + llvm_compilation_unit)); + } else +#endif + { + switch (compiler.GetInstructionSet()) { + case kThumb2: + cu->cg.reset(ArmCodeGenerator(cu.get(), cu->mir_graph.get(), &cu->arena)); break; + case kMips: + cu->cg.reset(MipsCodeGenerator(cu.get(), cu->mir_graph.get(), &cu->arena)); break; + case kX86: + cu->cg.reset(X86CodeGenerator(cu.get(), cu->mir_graph.get(), &cu->arena)); break; + default: + LOG(FATAL) << "Unexpected instruction set: " << compiler.GetInstructionSet(); + } + } + + cu->cg->Materialize(); + + result = cu->cg->GetCompiledMethod(); + + if (result) { + VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file); + } else { + VLOG(compiler) << "Deferred " << PrettyMethod(method_idx, dex_file); + } + + if (cu->enable_debug & (1 << kDebugShowMemoryUsage)) { + if (cu->arena.BytesAllocated() > (5 * 1024 *1024)) { + MemStats mem_stats(cu->arena); + LOG(INFO) << PrettyMethod(method_idx, dex_file) << " " << Dumpable<MemStats>(mem_stats); + } + } + + if (cu->enable_debug & (1 << kDebugShowSummaryMemoryUsage)) { + LOG(INFO) << "MEMINFO " << cu->arena.BytesAllocated() << " " << cu->mir_graph->GetNumBlocks() + << " " << PrettyMethod(method_idx, dex_file); + } + + return result; +} + +CompiledMethod* CompileOneMethod(CompilerDriver& compiler, + const CompilerBackend backend, + const DexFile::CodeItem* code_item, + uint32_t access_flags, + InvokeType invoke_type, + uint32_t class_def_idx, + uint32_t method_idx, + jobject class_loader, + const DexFile& dex_file, + llvm::LlvmCompilationUnit* llvm_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 + ); +} + +} // namespace art + +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) { + // TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default + 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 */); +} |