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