frontend.cc revision 6a58cb16d803c9a7b3a75ccac8be19dd9d4e520d
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 cu.target64 = (cu.instruction_set == kX86_64) || (cu.instruction_set == kArm64); 159 cu.compiler = compiler; 160 // TODO: x86_64 & arm64 are not yet implemented. 161 DCHECK((cu.instruction_set == kThumb2) || 162 (cu.instruction_set == kX86) || 163 (cu.instruction_set == kX86_64) || 164 (cu.instruction_set == kMips)); 165 166 167 /* Adjust this value accordingly once inlining is performed */ 168 cu.num_dalvik_registers = code_item->registers_size_; 169 // TODO: set this from command line 170 cu.compiler_flip_match = false; 171 bool use_match = !cu.compiler_method_match.empty(); 172 bool match = use_match && (cu.compiler_flip_match ^ 173 (PrettyMethod(method_idx, dex_file).find(cu.compiler_method_match) != 174 std::string::npos)); 175 if (!use_match || match) { 176 cu.disable_opt = kCompilerOptimizerDisableFlags; 177 cu.enable_debug = kCompilerDebugFlags; 178 cu.verbose = VLOG_IS_ON(compiler) || 179 (cu.enable_debug & (1 << kDebugVerbose)); 180 } 181 182 /* 183 * TODO: rework handling of optimization and debug flags. Should we split out 184 * MIR and backend flags? Need command-line setting as well. 185 */ 186 187 compiler->InitCompilationUnit(cu); 188 189 if (cu.instruction_set == kMips) { 190 // Disable some optimizations for mips for now 191 cu.disable_opt |= ( 192 (1 << kLoadStoreElimination) | 193 (1 << kLoadHoisting) | 194 (1 << kSuppressLoads) | 195 (1 << kNullCheckElimination) | 196 (1 << kPromoteRegs) | 197 (1 << kTrackLiveTemps) | 198 (1 << kSafeOptimizations) | 199 (1 << kBBOpt) | 200 (1 << kMatch) | 201 (1 << kPromoteCompilerTemps)); 202 } 203 204 cu.StartTimingSplit("BuildMIRGraph"); 205 cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena)); 206 207 /* 208 * After creation of the MIR graph, also create the code generator. 209 * The reason we do this is that optimizations on the MIR graph may need to get information 210 * that is only available if a CG exists. 211 */ 212 cu.cg.reset(compiler->GetCodeGenerator(&cu, llvm_compilation_unit)); 213 214 /* Gathering opcode stats? */ 215 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { 216 cu.mir_graph->EnableOpcodeCounting(); 217 } 218 219 // Check early if we should skip this compilation if using the profiled filter. 220 if (cu.compiler_driver->ProfilePresent()) { 221 std::string methodname = PrettyMethod(method_idx, dex_file); 222 if (cu.mir_graph->SkipCompilation(methodname)) { 223 return NULL; 224 } 225 } 226 227 /* Build the raw MIR graph */ 228 cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, 229 class_loader, dex_file); 230 231 cu.NewTimingSplit("MIROpt:CheckFilters"); 232 if (cu.mir_graph->SkipCompilation()) { 233 return NULL; 234 } 235 236 /* Create the pass driver and launch it */ 237 PassDriver pass_driver(&cu); 238 pass_driver.Launch(); 239 240 if (cu.enable_debug & (1 << kDebugDumpCheckStats)) { 241 cu.mir_graph->DumpCheckStats(); 242 } 243 244 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { 245 cu.mir_graph->ShowOpcodeStats(); 246 } 247 248 /* Reassociate sreg names with original Dalvik vreg names. */ 249 cu.mir_graph->RemapRegLocations(); 250 251 /* Free Arenas from the cu.arena_stack for reuse by the cu.arena in the codegen. */ 252 if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) { 253 if (cu.arena_stack.PeakBytesAllocated() > 256 * 1024) { 254 MemStats stack_stats(cu.arena_stack.GetPeakStats()); 255 LOG(INFO) << PrettyMethod(method_idx, dex_file) << " " << Dumpable<MemStats>(stack_stats); 256 } 257 } 258 cu.arena_stack.Reset(); 259 260 CompiledMethod* result = NULL; 261 262 cu.cg->Materialize(); 263 264 cu.NewTimingSplit("Dedupe"); /* deduping takes up the vast majority of time in GetCompiledMethod(). */ 265 result = cu.cg->GetCompiledMethod(); 266 cu.NewTimingSplit("Cleanup"); 267 268 if (result) { 269 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file); 270 } else { 271 VLOG(compiler) << "Deferred " << PrettyMethod(method_idx, dex_file); 272 } 273 274 if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) { 275 if (cu.arena.BytesAllocated() > (1 * 1024 *1024)) { 276 MemStats mem_stats(cu.arena.GetMemStats()); 277 LOG(INFO) << PrettyMethod(method_idx, dex_file) << " " << Dumpable<MemStats>(mem_stats); 278 } 279 } 280 281 if (cu.enable_debug & (1 << kDebugShowSummaryMemoryUsage)) { 282 LOG(INFO) << "MEMINFO " << cu.arena.BytesAllocated() << " " << cu.mir_graph->GetNumBlocks() 283 << " " << PrettyMethod(method_idx, dex_file); 284 } 285 286 cu.EndTiming(); 287 driver.GetTimingsLogger()->AddLogger(cu.timings); 288 return result; 289} 290 291CompiledMethod* CompileOneMethod(CompilerDriver& driver, 292 Compiler* compiler, 293 const DexFile::CodeItem* code_item, 294 uint32_t access_flags, 295 InvokeType invoke_type, 296 uint16_t class_def_idx, 297 uint32_t method_idx, 298 jobject class_loader, 299 const DexFile& dex_file, 300 void* compilation_unit) { 301 return CompileMethod(driver, compiler, code_item, access_flags, invoke_type, class_def_idx, 302 method_idx, class_loader, dex_file, compilation_unit); 303} 304 305} // namespace art 306 307extern "C" art::CompiledMethod* 308 ArtQuickCompileMethod(art::CompilerDriver& driver, 309 const art::DexFile::CodeItem* code_item, 310 uint32_t access_flags, art::InvokeType invoke_type, 311 uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, 312 const art::DexFile& dex_file) { 313 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default 314 art::Compiler* compiler = driver.GetCompiler(); 315 return art::CompileOneMethod(driver, compiler, code_item, access_flags, invoke_type, 316 class_def_idx, method_idx, class_loader, dex_file, 317 NULL /* use thread llvm_info */); 318} 319