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