frontend.cc revision 83cc7ae96d4176533dd0391a1591d321b0a87f4f
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 arena_stack(pool), 102 mir_graph(NULL), 103 cg(NULL), 104 timings("QuickCompiler", true, false) { 105} 106 107CompilationUnit::~CompilationUnit() { 108} 109 110void CompilationUnit::StartTimingSplit(const char* label) { 111 if (compiler_driver->GetDumpPasses()) { 112 timings.StartSplit(label); 113 } 114} 115 116void CompilationUnit::NewTimingSplit(const char* label) { 117 if (compiler_driver->GetDumpPasses()) { 118 timings.NewSplit(label); 119 } 120} 121 122void CompilationUnit::EndTiming() { 123 if (compiler_driver->GetDumpPasses()) { 124 timings.EndSplit(); 125 if (enable_debug & (1 << kDebugTimings)) { 126 LOG(INFO) << "TIMINGS " << PrettyMethod(method_idx, *dex_file); 127 LOG(INFO) << Dumpable<TimingLogger>(timings); 128 } 129 } 130} 131 132static CompiledMethod* CompileMethod(CompilerDriver& driver, 133 CompilerBackend* compiler_backend, 134 const DexFile::CodeItem* code_item, 135 uint32_t access_flags, InvokeType invoke_type, 136 uint16_t class_def_idx, uint32_t method_idx, 137 jobject class_loader, const DexFile& dex_file, 138 void* llvm_compilation_unit) { 139 VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "..."; 140 if (code_item->insns_size_in_code_units_ >= 0x10000) { 141 LOG(INFO) << "Method size exceeds compiler limits: " << code_item->insns_size_in_code_units_ 142 << " in " << PrettyMethod(method_idx, dex_file); 143 return NULL; 144 } 145 146 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 147 CompilationUnit cu(driver.GetArenaPool()); 148 149 cu.compiler_driver = &driver; 150 cu.class_linker = class_linker; 151 cu.instruction_set = driver.GetInstructionSet(); 152 cu.target64 = cu.instruction_set == kX86_64; 153 cu.compiler_backend = compiler_backend; 154 // TODO: x86_64 is not yet implemented. 155 DCHECK((cu.instruction_set == kThumb2) || 156 (cu.instruction_set == kX86) || 157 (cu.instruction_set == kMips)); 158 159 160 /* Adjust this value accordingly once inlining is performed */ 161 cu.num_dalvik_registers = code_item->registers_size_; 162 // TODO: set this from command line 163 cu.compiler_flip_match = false; 164 bool use_match = !cu.compiler_method_match.empty(); 165 bool match = use_match && (cu.compiler_flip_match ^ 166 (PrettyMethod(method_idx, dex_file).find(cu.compiler_method_match) != 167 std::string::npos)); 168 if (!use_match || match) { 169 cu.disable_opt = kCompilerOptimizerDisableFlags; 170 cu.enable_debug = kCompilerDebugFlags; 171 cu.verbose = VLOG_IS_ON(compiler) || 172 (cu.enable_debug & (1 << kDebugVerbose)); 173 } 174 175 /* 176 * TODO: rework handling of optimization and debug flags. Should we split out 177 * MIR and backend flags? Need command-line setting as well. 178 */ 179 180 compiler_backend->InitCompilationUnit(cu); 181 182 if (cu.instruction_set == kMips) { 183 // Disable some optimizations for mips for now 184 cu.disable_opt |= ( 185 (1 << kLoadStoreElimination) | 186 (1 << kLoadHoisting) | 187 (1 << kSuppressLoads) | 188 (1 << kNullCheckElimination) | 189 (1 << kPromoteRegs) | 190 (1 << kTrackLiveTemps) | 191 (1 << kSafeOptimizations) | 192 (1 << kBBOpt) | 193 (1 << kMatch) | 194 (1 << kPromoteCompilerTemps)); 195 } 196 197 cu.StartTimingSplit("BuildMIRGraph"); 198 cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena)); 199 200 /* 201 * After creation of the MIR graph, also create the code generator. 202 * The reason we do this is that optimizations on the MIR graph may need to get information 203 * that is only available if a CG exists. 204 */ 205 cu.cg.reset(compiler_backend->GetCodeGenerator(&cu, llvm_compilation_unit)); 206 207 /* Gathering opcode stats? */ 208 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { 209 cu.mir_graph->EnableOpcodeCounting(); 210 } 211 212 /* Build the raw MIR graph */ 213 cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, 214 class_loader, dex_file); 215 216 cu.NewTimingSplit("MIROpt:CheckFilters"); 217 if (cu.mir_graph->SkipCompilation()) { 218 return NULL; 219 } 220 221 /* Create the pass driver and launch it */ 222 PassDriver pass_driver(&cu); 223 pass_driver.Launch(); 224 225 if (cu.enable_debug & (1 << kDebugDumpCheckStats)) { 226 cu.mir_graph->DumpCheckStats(); 227 } 228 229 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) { 230 cu.mir_graph->ShowOpcodeStats(); 231 } 232 233 /* Reassociate sreg names with original Dalvik vreg names. */ 234 cu.mir_graph->RemapRegLocations(); 235 236 CompiledMethod* result = NULL; 237 238 cu.cg->Materialize(); 239 240 cu.NewTimingSplit("Dedupe"); /* deduping takes up the vast majority of time in GetCompiledMethod(). */ 241 result = cu.cg->GetCompiledMethod(); 242 cu.NewTimingSplit("Cleanup"); 243 244 if (result) { 245 VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file); 246 } else { 247 VLOG(compiler) << "Deferred " << PrettyMethod(method_idx, dex_file); 248 } 249 250 if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) { 251 if (cu.arena.BytesAllocated() > (1 * 1024 *1024) || 252 cu.arena_stack.PeakBytesAllocated() > 256 * 1024) { 253 MemStats mem_stats(cu.arena.GetMemStats()); 254 MemStats peak_stats(cu.arena_stack.GetPeakStats()); 255 LOG(INFO) << PrettyMethod(method_idx, dex_file) << " " << Dumpable<MemStats>(mem_stats) 256 << Dumpable<MemStats>(peak_stats); 257 } 258 } 259 260 if (cu.enable_debug & (1 << kDebugShowSummaryMemoryUsage)) { 261 LOG(INFO) << "MEMINFO " << cu.arena.BytesAllocated() << " " << cu.mir_graph->GetNumBlocks() 262 << " " << PrettyMethod(method_idx, dex_file); 263 } 264 265 cu.EndTiming(); 266 driver.GetTimingsLogger()->Start(); 267 driver.GetTimingsLogger()->AddLogger(cu.timings); 268 driver.GetTimingsLogger()->End(); 269 return result; 270} 271 272CompiledMethod* CompileOneMethod(CompilerDriver& compiler, 273 CompilerBackend* backend, 274 const DexFile::CodeItem* code_item, 275 uint32_t access_flags, 276 InvokeType invoke_type, 277 uint16_t class_def_idx, 278 uint32_t method_idx, 279 jobject class_loader, 280 const DexFile& dex_file, 281 void* compilation_unit) { 282 return CompileMethod(compiler, backend, code_item, access_flags, invoke_type, class_def_idx, 283 method_idx, class_loader, dex_file, compilation_unit); 284} 285 286} // namespace art 287 288extern "C" art::CompiledMethod* 289 ArtQuickCompileMethod(art::CompilerDriver& compiler, 290 const art::DexFile::CodeItem* code_item, 291 uint32_t access_flags, art::InvokeType invoke_type, 292 uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, 293 const art::DexFile& dex_file) { 294 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use build default 295 art::CompilerBackend* backend = compiler.GetCompilerBackend(); 296 return art::CompileOneMethod(compiler, backend, code_item, access_flags, invoke_type, 297 class_def_idx, method_idx, class_loader, dex_file, 298 NULL /* use thread llvm_info */); 299} 300