frontend.cc revision f5df8974173124faddb8e2b6a331959afdb94fdf
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 "compiler_backend.h" 18#include "compiler_internals.h" 19#include "driver/compiler_driver.h" 20#include "dataflow_iterator-inl.h" 21#include "leb128.h" 22#include "mirror/object.h" 23#include "pass_driver.h" 24#include "runtime.h" 25#include "backend.h" 26#include "base/logging.h" 27#include "base/timing_logger.h" 28 29#include "dex/quick/dex_file_to_method_inliner_map.h" 30 31namespace art { 32 33extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver) { 34 CHECK(driver.GetCompilerContext() == NULL); 35} 36 37extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& driver) { 38 CHECK(driver.GetCompilerContext() == NULL); 39} 40 41/* Default optimizer/debug setting for the compiler. */ 42static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations 43 (1 << kLoadStoreElimination) | 44 // (1 << kLoadHoisting) | 45 // (1 << kSuppressLoads) | 46 // (1 << kNullCheckElimination) | 47 // (1 << kPromoteRegs) | 48 // (1 << kTrackLiveTemps) | 49 // (1 << kSafeOptimizations) | 50 // (1 << kBBOpt) | 51 // (1 << kMatch) | 52 // (1 << kPromoteCompilerTemps) | 53 // (1 << kSuppressExceptionEdges) | 54 0; 55 56static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes 57 // (1 << kDebugDisplayMissingTargets) | 58 // (1 << kDebugVerbose) | 59 // (1 << kDebugDumpCFG) | 60 // (1 << kDebugSlowFieldPath) | 61 // (1 << kDebugSlowInvokePath) | 62 // (1 << kDebugSlowStringPath) | 63 // (1 << kDebugSlowestFieldPath) | 64 // (1 << kDebugSlowestStringPath) | 65 // (1 << kDebugExerciseResolveMethod) | 66 // (1 << kDebugVerifyDataflow) | 67 // (1 << kDebugShowMemoryUsage) | 68 // (1 << kDebugShowNops) | 69 // (1 << kDebugCountOpcodes) | 70 // (1 << kDebugDumpCheckStats) | 71 // (1 << kDebugDumpBitcodeFile) | 72 // (1 << kDebugVerifyBitcode) | 73 // (1 << kDebugShowSummaryMemoryUsage) | 74 // (1 << kDebugShowFilterStats) | 75 // (1 << kDebugTimings) | 76 0; 77 78CompilationUnit::CompilationUnit(ArenaPool* pool) 79 : compiler_driver(NULL), 80 class_linker(NULL), 81 dex_file(NULL), 82 class_loader(NULL), 83 class_def_idx(0), 84 method_idx(0), 85 code_item(NULL), 86 access_flags(0), 87 invoke_type(kDirect), 88 shorty(NULL), 89 disable_opt(0), 90 enable_debug(0), 91 verbose(false), 92 compiler_backend(NULL), 93 instruction_set(kNone), 94 num_dalvik_registers(0), 95 insns(NULL), 96 num_ins(0), 97 num_outs(0), 98 num_regs(0), 99 compiler_flip_match(false), 100 arena(pool), 101 mir_graph(NULL), 102 cg(NULL), 103 timings("QuickCompiler", true, false) { 104} 105 106CompilationUnit::~CompilationUnit() { 107} 108 109void CompilationUnit::StartTimingSplit(const char* label) { 110 if (compiler_driver->GetDumpPasses()) { 111 timings.StartSplit(label); 112 } 113} 114 115void CompilationUnit::NewTimingSplit(const char* label) { 116 if (compiler_driver->GetDumpPasses()) { 117 timings.NewSplit(label); 118 } 119} 120 121void CompilationUnit::EndTiming() { 122 if (compiler_driver->GetDumpPasses()) { 123 timings.EndSplit(); 124 if (enable_debug & (1 << kDebugTimings)) { 125 LOG(INFO) << "TIMINGS " << PrettyMethod(method_idx, *dex_file); 126 LOG(INFO) << Dumpable<TimingLogger>(timings); 127 } 128 } 129} 130 131static CompiledMethod* CompileMethod(CompilerDriver& compiler, 132 CompilerBackend* compiler_backend, 133 const DexFile::CodeItem* code_item, 134 uint32_t access_flags, InvokeType invoke_type, 135 uint16_t class_def_idx, uint32_t method_idx, 136 jobject class_loader, const DexFile& dex_file, 137 void* llvm_compilation_unit) { 138 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "..."; 139 if (code_item->insns_size_in_code_units_ >= 0x10000) { 140 LOG(INFO) << "Method size exceeds compiler limits: " << code_item->insns_size_in_code_units_ 141 << " in " << PrettyMethod(method_idx, dex_file); 142 return NULL; 143 } 144 145 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 146 CompilationUnit cu(&compiler.GetArenaPool()); 147 148 cu.compiler_driver = &compiler; 149 cu.class_linker = class_linker; 150 cu.instruction_set = compiler.GetInstructionSet(); 151 cu.compiler_backend = compiler_backend; 152 DCHECK((cu.instruction_set == kThumb2) || 153 (cu.instruction_set == kX86) || 154 (cu.instruction_set == kMips)); 155 156 157 /* Adjust this value accordingly once inlining is performed */ 158 cu.num_dalvik_registers = code_item->registers_size_; 159 // TODO: set this from command line 160 cu.compiler_flip_match = false; 161 bool use_match = !cu.compiler_method_match.empty(); 162 bool match = use_match && (cu.compiler_flip_match ^ 163 (PrettyMethod(method_idx, dex_file).find(cu.compiler_method_match) != 164 std::string::npos)); 165 if (!use_match || match) { 166 cu.disable_opt = kCompilerOptimizerDisableFlags; 167 cu.enable_debug = kCompilerDebugFlags; 168 cu.verbose = VLOG_IS_ON(compiler) || 169 (cu.enable_debug & (1 << kDebugVerbose)); 170 } 171 172 /* 173 * TODO: rework handling of optimization and debug flags. Should we split out 174 * MIR and backend flags? Need command-line setting as well. 175 */ 176 177 compiler_backend->InitCompilationUnit(cu); 178 179 if (cu.instruction_set == kMips) { 180 // Disable some optimizations for mips for now 181 cu.disable_opt |= ( 182 (1 << kLoadStoreElimination) | 183 (1 << kLoadHoisting) | 184 (1 << kSuppressLoads) | 185 (1 << kNullCheckElimination) | 186 (1 << kPromoteRegs) | 187 (1 << kTrackLiveTemps) | 188 (1 << kSafeOptimizations) | 189 (1 << kBBOpt) | 190 (1 << kMatch) | 191 (1 << kPromoteCompilerTemps)); 192 } 193 194 cu.StartTimingSplit("BuildMIRGraph"); 195 cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena)); 196 197 /* 198 * After creation of the MIR graph, also create the code generator. 199 * The reason we do this is that optimizations on the MIR graph may need to get information 200 * that is only available if a CG exists. 201 */ 202 cu.cg.reset(compiler_backend->GetCodeGenerator(&cu, llvm_compilation_unit)); 203 204 /* Gathering opcode stats? */ 205 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { 206 cu.mir_graph->EnableOpcodeCounting(); 207 } 208 209 /* Build the raw MIR graph */ 210 cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, 211 class_loader, dex_file); 212 213 cu.NewTimingSplit("MIROpt:CheckFilters"); 214 if (cu.mir_graph->SkipCompilation(Runtime::Current()->GetCompilerFilter())) { 215 return NULL; 216 } 217 218 /* Create the pass driver and launch it */ 219 PassDriver driver(&cu); 220 driver.Launch(); 221 222 if (cu.enable_debug & (1 << kDebugDumpCheckStats)) { 223 cu.mir_graph->DumpCheckStats(); 224 } 225 226 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { 227 cu.mir_graph->ShowOpcodeStats(); 228 } 229 230 /* Reassociate sreg names with original Dalvik vreg names. */ 231 cu.mir_graph->RemapRegLocations(); 232 233 CompiledMethod* result = NULL; 234 235 cu.cg->Materialize(); 236 237 cu.NewTimingSplit("Dedupe"); /* deduping takes up the vast majority of time in GetCompiledMethod(). */ 238 result = cu.cg->GetCompiledMethod(); 239 cu.NewTimingSplit("Cleanup"); 240 241 if (result) { 242 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file); 243 } else { 244 VLOG(compiler) << "Deferred " << PrettyMethod(method_idx, dex_file); 245 } 246 247 if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) { 248 if (cu.arena.BytesAllocated() > (5 * 1024 *1024)) { 249 MemStats mem_stats(cu.arena); 250 LOG(INFO) << PrettyMethod(method_idx, dex_file) << " " << Dumpable<MemStats>(mem_stats); 251 } 252 } 253 254 if (cu.enable_debug & (1 << kDebugShowSummaryMemoryUsage)) { 255 LOG(INFO) << "MEMINFO " << cu.arena.BytesAllocated() << " " << cu.mir_graph->GetNumBlocks() 256 << " " << PrettyMethod(method_idx, dex_file); 257 } 258 259 cu.EndTiming(); 260 compiler.GetTimingsLogger().Start(); 261 compiler.GetTimingsLogger().AddLogger(cu.timings); 262 compiler.GetTimingsLogger().End(); 263 return result; 264} 265 266CompiledMethod* CompileOneMethod(CompilerDriver& compiler, 267 CompilerBackend* backend, 268 const DexFile::CodeItem* code_item, 269 uint32_t access_flags, 270 InvokeType invoke_type, 271 uint16_t class_def_idx, 272 uint32_t method_idx, 273 jobject class_loader, 274 const DexFile& dex_file, 275 void* compilation_unit) { 276 return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, class_def_idx, 277 method_idx, class_loader, dex_file, compilation_unit); 278} 279 280} // namespace art 281 282extern "C" art::CompiledMethod* 283 ArtQuickCompileMethod(art::CompilerDriver& compiler, 284 const art::DexFile::CodeItem* code_item, 285 uint32_t access_flags, art::InvokeType invoke_type, 286 uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, 287 const art::DexFile& dex_file) { 288 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default 289 art::CompilerBackend* backend = compiler.GetCompilerBackend(); 290 return art::CompileOneMethod(compiler, backend, code_item, access_flags, invoke_type, 291 class_def_idx, method_idx, class_loader, dex_file, 292 NULL /* use thread llvm_info */); 293} 294