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