frontend.cc revision 4e97c539408f47145526f0062c1c06df99146a73
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 "pass_driver.h"
25#include "runtime.h"
26#include "backend.h"
27#include "base/logging.h"
28#include "base/timing_logger.h"
29
30#if defined(ART_USE_PORTABLE_COMPILER)
31#include "dex/portable/mir_to_gbc.h"
32#include "llvm/llvm_compilation_unit.h"
33#endif
34
35#include "dex/quick/dex_file_to_method_inliner_map.h"
36
37namespace {
38#if !defined(ART_USE_PORTABLE_COMPILER)
39  pthread_once_t llvm_multi_init = PTHREAD_ONCE_INIT;
40#endif
41  void InitializeLLVMForQuick() {
42    ::llvm::llvm_start_multithreaded();
43  }
44}
45
46namespace art {
47namespace llvm {
48::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);
49}
50
51LLVMInfo::LLVMInfo() {
52#if !defined(ART_USE_PORTABLE_COMPILER)
53  pthread_once(&llvm_multi_init, InitializeLLVMForQuick);
54#endif
55  // Create context, module, intrinsic helper & ir builder
56  llvm_context_.reset(new ::llvm::LLVMContext());
57  llvm_module_ = new ::llvm::Module("art", *llvm_context_);
58  ::llvm::StructType::create(*llvm_context_, "JavaObject");
59  art::llvm::makeLLVMModuleContents(llvm_module_);
60  intrinsic_helper_.reset(new art::llvm::IntrinsicHelper(*llvm_context_, *llvm_module_));
61  ir_builder_.reset(new art::llvm::IRBuilder(*llvm_context_, *llvm_module_, *intrinsic_helper_));
62}
63
64LLVMInfo::~LLVMInfo() {
65}
66
67extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver) {
68  CHECK(driver.GetCompilerContext() == NULL);
69}
70
71extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& driver) {
72  CHECK(driver.GetCompilerContext() == NULL);
73}
74
75/* Default optimizer/debug setting for the compiler. */
76static uint32_t kCompilerOptimizerDisableFlags = 0 |  // Disable specific optimizations
77  (1 << kLoadStoreElimination) |
78  // (1 << kLoadHoisting) |
79  // (1 << kSuppressLoads) |
80  // (1 << kNullCheckElimination) |
81  // (1 << kPromoteRegs) |
82  // (1 << kTrackLiveTemps) |
83  // (1 << kSafeOptimizations) |
84  // (1 << kBBOpt) |
85  // (1 << kMatch) |
86  // (1 << kPromoteCompilerTemps) |
87  // (1 << kSuppressExceptionEdges) |
88  0;
89
90static uint32_t kCompilerDebugFlags = 0 |     // Enable debug/testing modes
91  // (1 << kDebugDisplayMissingTargets) |
92  // (1 << kDebugVerbose) |
93  // (1 << kDebugDumpCFG) |
94  // (1 << kDebugSlowFieldPath) |
95  // (1 << kDebugSlowInvokePath) |
96  // (1 << kDebugSlowStringPath) |
97  // (1 << kDebugSlowestFieldPath) |
98  // (1 << kDebugSlowestStringPath) |
99  // (1 << kDebugExerciseResolveMethod) |
100  // (1 << kDebugVerifyDataflow) |
101  // (1 << kDebugShowMemoryUsage) |
102  // (1 << kDebugShowNops) |
103  // (1 << kDebugCountOpcodes) |
104  // (1 << kDebugDumpCheckStats) |
105  // (1 << kDebugDumpBitcodeFile) |
106  // (1 << kDebugVerifyBitcode) |
107  // (1 << kDebugShowSummaryMemoryUsage) |
108  // (1 << kDebugShowFilterStats) |
109  // (1 << kDebugTimings) |
110  0;
111
112CompilationUnit::CompilationUnit(ArenaPool* pool)
113  : compiler_driver(NULL),
114    class_linker(NULL),
115    dex_file(NULL),
116    class_loader(NULL),
117    class_def_idx(0),
118    method_idx(0),
119    code_item(NULL),
120    access_flags(0),
121    invoke_type(kDirect),
122    shorty(NULL),
123    disable_opt(0),
124    enable_debug(0),
125    verbose(false),
126    compiler_backend(kNoBackend),
127    instruction_set(kNone),
128    num_dalvik_registers(0),
129    insns(NULL),
130    num_ins(0),
131    num_outs(0),
132    num_regs(0),
133    num_compiler_temps(0),
134    compiler_flip_match(false),
135    arena(pool),
136    mir_graph(NULL),
137    cg(NULL),
138    timings("QuickCompiler", true, false) {
139}
140
141CompilationUnit::~CompilationUnit() {
142}
143
144// TODO: Add a cumulative version of logging, and combine with dex2oat --dump-timing
145void CompilationUnit::StartTimingSplit(const char* label) {
146  if (enable_debug & (1 << kDebugTimings)) {
147    timings.StartSplit(label);
148  }
149}
150
151void CompilationUnit::NewTimingSplit(const char* label) {
152  if (enable_debug & (1 << kDebugTimings)) {
153    timings.NewSplit(label);
154  }
155}
156
157void CompilationUnit::EndTiming() {
158  if (enable_debug & (1 << kDebugTimings)) {
159    timings.EndSplit();
160    LOG(INFO) << "TIMINGS " << PrettyMethod(method_idx, *dex_file);
161    LOG(INFO) << Dumpable<TimingLogger>(timings);
162  }
163}
164
165static CompiledMethod* CompileMethod(CompilerDriver& compiler,
166                                     const CompilerBackend compiler_backend,
167                                     const DexFile::CodeItem* code_item,
168                                     uint32_t access_flags, InvokeType invoke_type,
169                                     uint16_t class_def_idx, uint32_t method_idx,
170                                     jobject class_loader, const DexFile& dex_file
171#if defined(ART_USE_PORTABLE_COMPILER)
172                                     , llvm::LlvmCompilationUnit* llvm_compilation_unit
173#endif
174) {
175  VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
176  if (code_item->insns_size_in_code_units_ >= 0x10000) {
177    LOG(INFO) << "Method size exceeds compiler limits: " << code_item->insns_size_in_code_units_
178              << " in " << PrettyMethod(method_idx, dex_file);
179    return NULL;
180  }
181
182  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
183  CompilationUnit cu(&compiler.GetArenaPool());
184
185  cu.compiler_driver = &compiler;
186  cu.class_linker = class_linker;
187  cu.instruction_set = compiler.GetInstructionSet();
188  cu.compiler_backend = compiler_backend;
189  DCHECK((cu.instruction_set == kThumb2) ||
190         (cu.instruction_set == kX86) ||
191         (cu.instruction_set == kMips));
192
193
194  /* Adjust this value accordingly once inlining is performed */
195  cu.num_dalvik_registers = code_item->registers_size_;
196  // TODO: set this from command line
197  cu.compiler_flip_match = false;
198  bool use_match = !cu.compiler_method_match.empty();
199  bool match = use_match && (cu.compiler_flip_match ^
200      (PrettyMethod(method_idx, dex_file).find(cu.compiler_method_match) !=
201       std::string::npos));
202  if (!use_match || match) {
203    cu.disable_opt = kCompilerOptimizerDisableFlags;
204    cu.enable_debug = kCompilerDebugFlags;
205    cu.verbose = VLOG_IS_ON(compiler) ||
206        (cu.enable_debug & (1 << kDebugVerbose));
207  }
208
209  /*
210   * TODO: rework handling of optimization and debug flags.  Should we split out
211   * MIR and backend flags?  Need command-line setting as well.
212   */
213
214  if (compiler_backend == kPortable) {
215    // Fused long branches not currently useful in bitcode.
216    cu.disable_opt |=
217        (1 << kBranchFusing) |
218        (1 << kSuppressExceptionEdges);
219  }
220
221  if (cu.instruction_set == kMips) {
222    // Disable some optimizations for mips for now
223    cu.disable_opt |= (
224        (1 << kLoadStoreElimination) |
225        (1 << kLoadHoisting) |
226        (1 << kSuppressLoads) |
227        (1 << kNullCheckElimination) |
228        (1 << kPromoteRegs) |
229        (1 << kTrackLiveTemps) |
230        (1 << kSafeOptimizations) |
231        (1 << kBBOpt) |
232        (1 << kMatch) |
233        (1 << kPromoteCompilerTemps));
234  }
235
236  cu.StartTimingSplit("BuildMIRGraph");
237  cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena));
238
239  /* Gathering opcode stats? */
240  if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
241    cu.mir_graph->EnableOpcodeCounting();
242  }
243
244  /* Build the raw MIR graph */
245  cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx,
246                              class_loader, dex_file);
247
248  cu.NewTimingSplit("MIROpt:CheckFilters");
249#if !defined(ART_USE_PORTABLE_COMPILER)
250  if (cu.mir_graph->SkipCompilation(Runtime::Current()->GetCompilerFilter())) {
251    return NULL;
252  }
253#endif
254
255  /* Create the pass driver and launch it */
256  PassDriver driver(&cu);
257  driver.Launch();
258
259  if (cu.enable_debug & (1 << kDebugDumpCheckStats)) {
260    cu.mir_graph->DumpCheckStats();
261  }
262
263  if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
264    cu.mir_graph->ShowOpcodeStats();
265  }
266
267  /* Reassociate sreg names with original Dalvik vreg names. */
268  cu.mir_graph->RemapRegLocations();
269
270  CompiledMethod* result = NULL;
271
272#if defined(ART_USE_PORTABLE_COMPILER)
273  if (compiler_backend == kPortable) {
274    cu.cg.reset(PortableCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena, llvm_compilation_unit));
275  } else {
276#endif
277    switch (compiler.GetInstructionSet()) {
278      case kThumb2:
279        cu.cg.reset(ArmCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena));
280        break;
281      case kMips:
282        cu.cg.reset(MipsCodeGenerator(&cu, cu.mir_graph.get(), &cu.arena));
283        break;
284      case kX86:
285        cu.cg.reset(X86CodeGenerator(&cu, cu.mir_graph.get(), &cu.arena));
286        break;
287      default:
288        LOG(FATAL) << "Unexpected instruction set: " << compiler.GetInstructionSet();
289    }
290#if defined(ART_USE_PORTABLE_COMPILER)
291  }
292#endif
293
294  cu.cg->Materialize();
295
296  cu.NewTimingSplit("Dedupe");  /* deduping takes up the vast majority of time in GetCompiledMethod(). */
297  result = cu.cg->GetCompiledMethod();
298  cu.NewTimingSplit("Cleanup");
299
300  if (result) {
301    VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file);
302  } else {
303    VLOG(compiler) << "Deferred " << PrettyMethod(method_idx, dex_file);
304  }
305
306  if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) {
307    if (cu.arena.BytesAllocated() > (5 * 1024 *1024)) {
308      MemStats mem_stats(cu.arena);
309      LOG(INFO) << PrettyMethod(method_idx, dex_file) << " " << Dumpable<MemStats>(mem_stats);
310    }
311  }
312
313  if (cu.enable_debug & (1 << kDebugShowSummaryMemoryUsage)) {
314    LOG(INFO) << "MEMINFO " << cu.arena.BytesAllocated() << " " << cu.mir_graph->GetNumBlocks()
315              << " " << PrettyMethod(method_idx, dex_file);
316  }
317
318  cu.EndTiming();
319  return result;
320}
321
322CompiledMethod* CompileOneMethod(CompilerDriver& compiler,
323                                 const CompilerBackend backend,
324                                 const DexFile::CodeItem* code_item,
325                                 uint32_t access_flags,
326                                 InvokeType invoke_type,
327                                 uint16_t class_def_idx,
328                                 uint32_t method_idx,
329                                 jobject class_loader,
330                                 const DexFile& dex_file,
331                                 llvm::LlvmCompilationUnit* llvm_compilation_unit) {
332  return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, class_def_idx,
333                       method_idx, class_loader, dex_file
334#if defined(ART_USE_PORTABLE_COMPILER)
335                       , llvm_compilation_unit
336#endif
337                       );  // NOLINT(whitespace/parens)
338}
339
340}  // namespace art
341
342extern "C" art::CompiledMethod*
343    ArtQuickCompileMethod(art::CompilerDriver& compiler,
344                          const art::DexFile::CodeItem* code_item,
345                          uint32_t access_flags, art::InvokeType invoke_type,
346                          uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
347                          const art::DexFile& dex_file) {
348  // TODO: check method fingerprint here to determine appropriate backend type.  Until then, use build default
349  art::CompilerBackend backend = compiler.GetCompilerBackend();
350  return art::CompileOneMethod(compiler, backend, code_item, access_flags, invoke_type,
351                               class_def_idx, method_idx, class_loader, dex_file,
352                               NULL /* use thread llvm_info */);
353}
354