Home | History | Annotate | Download | only in compiler
      1 /*
      2  * Copyright (C) 2014 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 "compiler.h"
     18 #include "compilers.h"
     19 #include "driver/compiler_driver.h"
     20 #include "mirror/art_method-inl.h"
     21 
     22 #ifdef ART_USE_PORTABLE_COMPILER
     23 #include "dex/portable/mir_to_gbc.h"
     24 #include "elf_writer_mclinker.h"
     25 #endif
     26 
     27 namespace art {
     28 
     29 #ifdef ART_SEA_IR_MODE
     30 extern "C" art::CompiledMethod* SeaIrCompileMethod(const art::DexFile::CodeItem* code_item,
     31                                                    uint32_t access_flags,
     32                                                    art::InvokeType invoke_type,
     33                                                    uint16_t class_def_idx,
     34                                                    uint32_t method_idx,
     35                                                    jobject class_loader,
     36                                                    const art::DexFile& dex_file);
     37 #endif
     38 
     39 
     40 CompiledMethod* Compiler::TryCompileWithSeaIR(const art::DexFile::CodeItem* code_item,
     41                                               uint32_t access_flags,
     42                                               art::InvokeType invoke_type,
     43                                               uint16_t class_def_idx,
     44                                               uint32_t method_idx,
     45                                               jobject class_loader,
     46                                               const art::DexFile& dex_file) {
     47 #ifdef ART_SEA_IR_MODE
     48     bool use_sea = (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
     49     if (use_sea) {
     50       LOG(INFO) << "Using SEA IR to compile..." << std::endl;
     51       return SeaIrCompileMethod(code_item,
     52                                 access_flags,
     53                                 invoke_type,
     54                                 class_def_idx,
     55                                 method_idx,
     56                                 class_loader,
     57                                 dex_file);
     58   }
     59 #endif
     60   return nullptr;
     61 }
     62 
     63 
     64 #ifdef ART_USE_PORTABLE_COMPILER
     65 
     66 extern "C" void ArtInitCompilerContext(art::CompilerDriver* driver);
     67 
     68 extern "C" void ArtUnInitCompilerContext(art::CompilerDriver* driver);
     69 
     70 extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver* driver,
     71                                                  const art::DexFile::CodeItem* code_item,
     72                                                  uint32_t access_flags,
     73                                                  art::InvokeType invoke_type,
     74                                                  uint16_t class_def_idx,
     75                                                  uint32_t method_idx,
     76                                                  jobject class_loader,
     77                                                  const art::DexFile& dex_file);
     78 
     79 extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver* driver,
     80                                                         uint32_t access_flags, uint32_t method_idx,
     81                                                         const art::DexFile& dex_file);
     82 
     83 extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver* driver,
     84                                                std::string const& filename);
     85 
     86 
     87 class LLVMCompiler FINAL : public Compiler {
     88  public:
     89   explicit LLVMCompiler(CompilerDriver* driver) : Compiler(driver, 1000) {}
     90 
     91   void Init() const OVERRIDE {
     92     ArtInitCompilerContext(GetCompilerDriver());
     93   }
     94 
     95   void UnInit() const OVERRIDE {
     96     ArtUnInitCompilerContext(GetCompilerDriver());
     97   }
     98 
     99   CompiledMethod* Compile(const DexFile::CodeItem* code_item,
    100                           uint32_t access_flags,
    101                           InvokeType invoke_type,
    102                           uint16_t class_def_idx,
    103                           uint32_t method_idx,
    104                           jobject class_loader,
    105                           const DexFile& dex_file) const OVERRIDE {
    106     CompiledMethod* method = TryCompileWithSeaIR(code_item,
    107                                                  access_flags,
    108                                                  invoke_type,
    109                                                  class_def_idx,
    110                                                  method_idx,
    111                                                  class_loader,
    112                                                  dex_file);
    113     if (method != nullptr) {
    114       return method;
    115     }
    116 
    117     return ArtCompileMethod(GetCompilerDriver(),
    118                             code_item,
    119                             access_flags,
    120                             invoke_type,
    121                             class_def_idx,
    122                             method_idx,
    123                             class_loader,
    124                             dex_file);
    125   }
    126 
    127   CompiledMethod* JniCompile(uint32_t access_flags,
    128                              uint32_t method_idx,
    129                              const DexFile& dex_file) const OVERRIDE {
    130     return ArtLLVMJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
    131   }
    132 
    133   uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
    134     return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
    135   }
    136 
    137   bool WriteElf(art::File* file,
    138                 OatWriter* oat_writer,
    139                 const std::vector<const art::DexFile*>& dex_files,
    140                 const std::string& android_root,
    141                 bool is_host, const CompilerDriver& driver) const
    142       OVERRIDE
    143       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    144     return art::ElfWriterMclinker::Create(
    145         file, oat_writer, dex_files, android_root, is_host, driver);
    146   }
    147 
    148   Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
    149     return PortableCodeGenerator(
    150         cu, cu->mir_graph.get(), &cu->arena,
    151         reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
    152   }
    153 
    154   void InitCompilationUnit(CompilationUnit& cu) const {
    155       // Fused long branches not currently useful in bitcode.
    156     cu.disable_opt |=
    157         (1 << kBranchFusing) |
    158         (1 << kSuppressExceptionEdges);
    159   }
    160 
    161   bool IsPortable() const OVERRIDE {
    162     return true;
    163   }
    164 
    165   void SetBitcodeFileName(const CompilerDriver& driver, const std::string& filename) {
    166     typedef void (*SetBitcodeFileNameFn)(const CompilerDriver&, const std::string&);
    167 
    168     SetBitcodeFileNameFn set_bitcode_file_name =
    169       reinterpret_cast<SetBitcodeFileNameFn>(compilerLLVMSetBitcodeFileName);
    170 
    171     set_bitcode_file_name(driver, filename);
    172   }
    173 
    174  private:
    175   DISALLOW_COPY_AND_ASSIGN(LLVMCompiler);
    176 };
    177 #endif
    178 
    179 Compiler* Compiler::Create(CompilerDriver* driver, Compiler::Kind kind) {
    180   switch (kind) {
    181     case kQuick:
    182       return new QuickCompiler(driver);
    183       break;
    184     case kOptimizing:
    185       return new OptimizingCompiler(driver);
    186       break;
    187     case kPortable:
    188 #ifdef ART_USE_PORTABLE_COMPILER
    189       return new LLVMCompiler(driver);
    190 #else
    191       LOG(FATAL) << "Portable compiler not compiled";
    192 #endif
    193       break;
    194     default:
    195       LOG(FATAL) << "UNREACHABLE";
    196   }
    197   return nullptr;
    198 }
    199 
    200 }  // namespace art
    201