Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <llvm/Support/Threading.h>
     18 
     19 #include "compiler_internals.h"
     20 #include "driver/compiler_driver.h"
     21 #include "dataflow_iterator-inl.h"
     22 #include "leb128.h"
     23 #include "mirror/object.h"
     24 #include "runtime.h"
     25 #include "backend.h"
     26 #include "base/logging.h"
     27 
     28 #if defined(ART_USE_PORTABLE_COMPILER)
     29 #include "dex/portable/mir_to_gbc.h"
     30 #include "llvm/llvm_compilation_unit.h"
     31 #endif
     32 
     33 namespace {
     34 #if !defined(ART_USE_PORTABLE_COMPILER)
     35   pthread_once_t llvm_multi_init = PTHREAD_ONCE_INIT;
     36 #endif
     37   void InitializeLLVMForQuick() {
     38     ::llvm::llvm_start_multithreaded();
     39   }
     40 }
     41 
     42 namespace art {
     43 namespace llvm {
     44 ::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);
     45 }
     46 
     47 LLVMInfo::LLVMInfo() {
     48 #if !defined(ART_USE_PORTABLE_COMPILER)
     49   pthread_once(&llvm_multi_init, InitializeLLVMForQuick);
     50 #endif
     51   // Create context, module, intrinsic helper & ir builder
     52   llvm_context_.reset(new ::llvm::LLVMContext());
     53   llvm_module_ = new ::llvm::Module("art", *llvm_context_);
     54   ::llvm::StructType::create(*llvm_context_, "JavaObject");
     55   art::llvm::makeLLVMModuleContents(llvm_module_);
     56   intrinsic_helper_.reset(new art::llvm::IntrinsicHelper(*llvm_context_, *llvm_module_));
     57   ir_builder_.reset(new art::llvm::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
     58 }
     59 
     60 LLVMInfo::~LLVMInfo() {
     61 }
     62 
     63 extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& compiler) {
     64   CHECK(compiler.GetCompilerContext() == NULL);
     65   LLVMInfo* llvm_info = new LLVMInfo();
     66   compiler.SetCompilerContext(llvm_info);
     67 }
     68 
     69 extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& compiler) {
     70   delete reinterpret_cast<LLVMInfo*>(compiler.GetCompilerContext());
     71   compiler.SetCompilerContext(NULL);
     72 }
     73 
     74 /* Default optimizer/debug setting for the compiler. */
     75 static uint32_t kCompilerOptimizerDisableFlags = 0 |  // Disable specific optimizations
     76   (1 << kLoadStoreElimination) |
     77   // (1 << kLoadHoisting) |
     78   // (1 << kSuppressLoads) |
     79   // (1 << kNullCheckElimination) |
     80   // (1 << kPromoteRegs) |
     81   // (1 << kTrackLiveTemps) |
     82   // (1 << kSafeOptimizations) |
     83   // (1 << kBBOpt) |
     84   // (1 << kMatch) |
     85   // (1 << kPromoteCompilerTemps) |
     86   0;
     87 
     88 static uint32_t kCompilerDebugFlags = 0 |     // Enable debug/testing modes
     89   // (1 << kDebugDisplayMissingTargets) |
     90   // (1 << kDebugVerbose) |
     91   // (1 << kDebugDumpCFG) |
     92   // (1 << kDebugSlowFieldPath) |
     93   // (1 << kDebugSlowInvokePath) |
     94   // (1 << kDebugSlowStringPath) |
     95   // (1 << kDebugSlowestFieldPath) |
     96   // (1 << kDebugSlowestStringPath) |
     97   // (1 << kDebugExerciseResolveMethod) |
     98   // (1 << kDebugVerifyDataflow) |
     99   // (1 << kDebugShowMemoryUsage) |
    100   // (1 << kDebugShowNops) |
    101   // (1 << kDebugCountOpcodes) |
    102   // (1 << kDebugDumpCheckStats) |
    103   // (1 << kDebugDumpBitcodeFile) |
    104   // (1 << kDebugVerifyBitcode) |
    105   // (1 << kDebugShowSummaryMemoryUsage) |
    106   // (1 << kDebugShowFilterStats) |
    107   0;
    108 
    109 static CompiledMethod* CompileMethod(CompilerDriver& compiler,
    110                                      const CompilerBackend compiler_backend,
    111                                      const DexFile::CodeItem* code_item,
    112                                      uint32_t access_flags, InvokeType invoke_type,
    113                                      uint16_t class_def_idx, uint32_t method_idx,
    114                                      jobject class_loader, const DexFile& dex_file
    115 #if defined(ART_USE_PORTABLE_COMPILER)
    116                                      , llvm::LlvmCompilationUnit* llvm_compilation_unit
    117 #endif
    118 ) {
    119   VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
    120 
    121   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    122   CompilationUnit cu(&compiler.GetArenaPool());
    123 
    124   cu.compiler_driver = &compiler;
    125   cu.class_linker = class_linker;
    126   cu.instruction_set = compiler.GetInstructionSet();
    127   cu.compiler_backend = compiler_backend;
    128   DCHECK((cu.instruction_set == kThumb2) ||
    129          (cu.instruction_set == kX86) ||
    130          (cu.instruction_set == kMips));
    131 
    132 
    133   /* Adjust this value accordingly once inlining is performed */
    134   cu.num_dalvik_registers = code_item->registers_size_;
    135   // TODO: set this from command line
    136   cu.compiler_flip_match = false;
    137   bool use_match = !cu.compiler_method_match.empty();
    138   bool match = use_match && (cu.compiler_flip_match ^
    139       (PrettyMethod(method_idx, dex_file).find(cu.compiler_method_match) !=
    140        std::string::npos));
    141   if (!use_match || match) {
    142     cu.disable_opt = kCompilerOptimizerDisableFlags;
    143     cu.enable_debug = kCompilerDebugFlags;
    144     cu.verbose = VLOG_IS_ON(compiler) ||
    145         (cu.enable_debug & (1 << kDebugVerbose));
    146   }
    147 
    148   /*
    149    * TODO: rework handling of optimization and debug flags.  Should we split out
    150    * MIR and backend flags?  Need command-line setting as well.
    151    */
    152 
    153   if (compiler_backend == kPortable) {
    154     // Fused long branches not currently usseful in bitcode.
    155     cu.disable_opt |= (1 << kBranchFusing);
    156   }
    157 
    158   if (cu.instruction_set == kMips) {
    159     // Disable some optimizations for mips for now
    160     cu.disable_opt |= (
    161         (1 << kLoadStoreElimination) |
    162         (1 << kLoadHoisting) |
    163         (1 << kSuppressLoads) |
    164         (1 << kNullCheckElimination) |
    165         (1 << kPromoteRegs) |
    166         (1 << kTrackLiveTemps) |
    167         (1 << kSafeOptimizations) |
    168         (1 << kBBOpt) |
    169         (1 << kMatch) |
    170         (1 << kPromoteCompilerTemps));
    171   }
    172 
    173   cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena));
    174 
    175   /* Gathering opcode stats? */
    176   if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
    177     cu.mir_graph->EnableOpcodeCounting();
    178   }
    179 
    180   /* Build the raw MIR graph */
    181   cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx,
    182                               class_loader, dex_file);
    183 
    184 #if !defined(ART_USE_PORTABLE_COMPILER)
    185   if (cu.mir_graph->SkipCompilation(Runtime::Current()->GetCompilerFilter())) {
    186     return NULL;
    187   }
    188 #endif
    189 
    190   /* Do a code layout pass */
    191   cu.mir_graph->CodeLayout();
    192 
    193   /* Perform SSA transformation for the whole method */
    194   cu.mir_graph->SSATransformation();
    195 
    196   /* Do constant propagation */
    197   cu.mir_graph->PropagateConstants();
    198 
    199   /* Count uses */
    200   cu.mir_graph->MethodUseCount();
    201 
    202   /* Perform null check elimination */
    203   cu.mir_graph->NullCheckElimination();
    204 
    205   /* Combine basic blocks where possible */
    206   cu.mir_graph->BasicBlockCombine();
    207 
    208   /* Do some basic block optimizations */
    209   cu.mir_graph->BasicBlockOptimization();
    210 
    211   if (cu.enable_debug & (1 << kDebugDumpCheckStats)) {
    212     cu.mir_graph->DumpCheckStats();
    213   }
    214 
    215   if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
    216     cu.mir_graph->ShowOpcodeStats();
    217   }
    218 
    219   /* Set up regLocation[] array to describe values - one for each ssa_name. */
    220   cu.mir_graph->BuildRegLocations();
    221 
    222   CompiledMethod* result = NULL;
    223 
    224 #if defined(ART_USE_PORTABLE_COMPILER)
    225   if (compiler_backend == kPortable) {
    226     cu.cg.reset(PortableCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena, llvm_compilation_unit));
    227   } else {
    228 #endif
    229     switch (compiler.GetInstructionSet()) {
    230       case kThumb2:
    231         cu.cg.reset(ArmCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena));
    232         break;
    233       case kMips:
    234         cu.cg.reset(MipsCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena));
    235         break;
    236       case kX86:
    237         cu.cg.reset(X86CodeGenerator(&cu, cu.mir_graph.get(), &cu.arena));
    238         break;
    239       default:
    240         LOG(FATAL) << "Unexpected instruction set: " << compiler.GetInstructionSet();
    241     }
    242 #if defined(ART_USE_PORTABLE_COMPILER)
    243   }
    244 #endif
    245 
    246   cu.cg->Materialize();
    247 
    248   result = cu.cg->GetCompiledMethod();
    249 
    250   if (result) {
    251     VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file);
    252   } else {
    253     VLOG(compiler) << "Deferred " << PrettyMethod(method_idx, dex_file);
    254   }
    255 
    256   if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) {
    257     if (cu.arena.BytesAllocated() > (5 * 1024 *1024)) {
    258       MemStats mem_stats(cu.arena);
    259       LOG(INFO) << PrettyMethod(method_idx, dex_file) << " " << Dumpable<MemStats>(mem_stats);
    260     }
    261   }
    262 
    263   if (cu.enable_debug & (1 << kDebugShowSummaryMemoryUsage)) {
    264     LOG(INFO) << "MEMINFO " << cu.arena.BytesAllocated() << " " << cu.mir_graph->GetNumBlocks()
    265               << " " << PrettyMethod(method_idx, dex_file);
    266   }
    267 
    268   return result;
    269 }
    270 
    271 CompiledMethod* CompileOneMethod(CompilerDriver& compiler,
    272                                  const CompilerBackend backend,
    273                                  const DexFile::CodeItem* code_item,
    274                                  uint32_t access_flags,
    275                                  InvokeType invoke_type,
    276                                  uint16_t class_def_idx,
    277                                  uint32_t method_idx,
    278                                  jobject class_loader,
    279                                  const DexFile& dex_file,
    280                                  llvm::LlvmCompilationUnit* llvm_compilation_unit) {
    281   return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, class_def_idx,
    282                        method_idx, class_loader, dex_file
    283 #if defined(ART_USE_PORTABLE_COMPILER)
    284                        , llvm_compilation_unit
    285 #endif
    286                        );  // NOLINT(whitespace/parens)
    287 }
    288 
    289 }  // namespace art
    290 
    291 extern "C" art::CompiledMethod*
    292     ArtQuickCompileMethod(art::CompilerDriver& compiler,
    293                           const art::DexFile::CodeItem* code_item,
    294                           uint32_t access_flags, art::InvokeType invoke_type,
    295                           uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
    296                           const art::DexFile& dex_file) {
    297   // TODO: check method fingerprint here to determine appropriate backend type.  Until then, use build default
    298   art::CompilerBackend backend = compiler.GetCompilerBackend();
    299   return art::CompileOneMethod(compiler, backend, code_item, access_flags, invoke_type,
    300                                class_def_idx, method_idx, class_loader, dex_file,
    301                                NULL /* use thread llvm_info */);
    302 }
    303