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