1 /* 2 * Copyright (C) 2014 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 "builder.h" 18 19 #include "art_field-inl.h" 20 #include "base/arena_bit_vector.h" 21 #include "base/bit_vector-inl.h" 22 #include "base/logging.h" 23 #include "block_builder.h" 24 #include "data_type-inl.h" 25 #include "dex/verified_method.h" 26 #include "driver/compiler_options.h" 27 #include "driver/dex_compilation_unit.h" 28 #include "instruction_builder.h" 29 #include "mirror/class_loader.h" 30 #include "mirror/dex_cache.h" 31 #include "nodes.h" 32 #include "optimizing_compiler_stats.h" 33 #include "ssa_builder.h" 34 #include "thread.h" 35 #include "utils/dex_cache_arrays_layout-inl.h" 36 37 namespace art { 38 39 HGraphBuilder::HGraphBuilder(HGraph* graph, 40 const CodeItemDebugInfoAccessor& accessor, 41 const DexCompilationUnit* dex_compilation_unit, 42 const DexCompilationUnit* outer_compilation_unit, 43 CompilerDriver* driver, 44 CodeGenerator* code_generator, 45 OptimizingCompilerStats* compiler_stats, 46 ArrayRef<const uint8_t> interpreter_metadata, 47 VariableSizedHandleScope* handles) 48 : graph_(graph), 49 dex_file_(&graph->GetDexFile()), 50 code_item_accessor_(accessor), 51 dex_compilation_unit_(dex_compilation_unit), 52 outer_compilation_unit_(outer_compilation_unit), 53 compiler_driver_(driver), 54 code_generator_(code_generator), 55 compilation_stats_(compiler_stats), 56 interpreter_metadata_(interpreter_metadata), 57 handles_(handles), 58 return_type_(DataType::FromShorty(dex_compilation_unit_->GetShorty()[0])) {} 59 60 HGraphBuilder::HGraphBuilder(HGraph* graph, 61 const DexCompilationUnit* dex_compilation_unit, 62 const CodeItemDebugInfoAccessor& accessor, 63 VariableSizedHandleScope* handles, 64 DataType::Type return_type) 65 : graph_(graph), 66 dex_file_(&graph->GetDexFile()), 67 code_item_accessor_(accessor), 68 dex_compilation_unit_(dex_compilation_unit), 69 outer_compilation_unit_(nullptr), 70 compiler_driver_(nullptr), 71 code_generator_(nullptr), 72 compilation_stats_(nullptr), 73 handles_(handles), 74 return_type_(return_type) {} 75 76 bool HGraphBuilder::SkipCompilation(size_t number_of_branches) { 77 if (compiler_driver_ == nullptr) { 78 // Note that the compiler driver is null when unit testing. 79 return false; 80 } 81 82 const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions(); 83 CompilerFilter::Filter compiler_filter = compiler_options.GetCompilerFilter(); 84 if (compiler_filter == CompilerFilter::kEverything) { 85 return false; 86 } 87 88 const uint32_t code_units = code_item_accessor_.InsnsSizeInCodeUnits(); 89 if (compiler_options.IsHugeMethod(code_units)) { 90 VLOG(compiler) << "Skip compilation of huge method " 91 << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex()) 92 << ": " << code_units << " code units"; 93 MaybeRecordStat(compilation_stats_, MethodCompilationStat::kNotCompiledHugeMethod); 94 return true; 95 } 96 97 // If it's large and contains no branches, it's likely to be machine generated initialization. 98 if (compiler_options.IsLargeMethod(code_units) && (number_of_branches == 0)) { 99 VLOG(compiler) << "Skip compilation of large method with no branch " 100 << dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex()) 101 << ": " << code_units << " code units"; 102 MaybeRecordStat(compilation_stats_, MethodCompilationStat::kNotCompiledLargeMethodNoBranches); 103 return true; 104 } 105 106 return false; 107 } 108 109 GraphAnalysisResult HGraphBuilder::BuildGraph() { 110 DCHECK(code_item_accessor_.HasCodeItem()); 111 DCHECK(graph_->GetBlocks().empty()); 112 113 graph_->SetNumberOfVRegs(code_item_accessor_.RegistersSize()); 114 graph_->SetNumberOfInVRegs(code_item_accessor_.InsSize()); 115 graph_->SetMaximumNumberOfOutVRegs(code_item_accessor_.OutsSize()); 116 graph_->SetHasTryCatch(code_item_accessor_.TriesSize() != 0); 117 118 // Use ScopedArenaAllocator for all local allocations. 119 ScopedArenaAllocator local_allocator(graph_->GetArenaStack()); 120 HBasicBlockBuilder block_builder(graph_, dex_file_, code_item_accessor_, &local_allocator); 121 SsaBuilder ssa_builder(graph_, 122 dex_compilation_unit_->GetClassLoader(), 123 dex_compilation_unit_->GetDexCache(), 124 handles_, 125 &local_allocator); 126 HInstructionBuilder instruction_builder(graph_, 127 &block_builder, 128 &ssa_builder, 129 dex_file_, 130 code_item_accessor_, 131 return_type_, 132 dex_compilation_unit_, 133 outer_compilation_unit_, 134 compiler_driver_, 135 code_generator_, 136 interpreter_metadata_, 137 compilation_stats_, 138 handles_, 139 &local_allocator); 140 141 // 1) Create basic blocks and link them together. Basic blocks are left 142 // unpopulated with the exception of synthetic blocks, e.g. HTryBoundaries. 143 if (!block_builder.Build()) { 144 return kAnalysisInvalidBytecode; 145 } 146 147 // 2) Decide whether to skip this method based on its code size and number 148 // of branches. 149 if (SkipCompilation(block_builder.GetNumberOfBranches())) { 150 return kAnalysisSkipped; 151 } 152 153 // 3) Build the dominator tree and fill in loop and try/catch metadata. 154 GraphAnalysisResult result = graph_->BuildDominatorTree(); 155 if (result != kAnalysisSuccess) { 156 return result; 157 } 158 159 // 4) Populate basic blocks with instructions. 160 if (!instruction_builder.Build()) { 161 return kAnalysisInvalidBytecode; 162 } 163 164 // 5) Type the graph and eliminate dead/redundant phis. 165 return ssa_builder.BuildSsa(); 166 } 167 168 void HGraphBuilder::BuildIntrinsicGraph(ArtMethod* method) { 169 DCHECK(!code_item_accessor_.HasCodeItem()); 170 DCHECK(graph_->GetBlocks().empty()); 171 172 // Determine the number of arguments and associated vregs. 173 uint32_t method_idx = dex_compilation_unit_->GetDexMethodIndex(); 174 const char* shorty = dex_file_->GetMethodShorty(dex_file_->GetMethodId(method_idx)); 175 size_t num_args = strlen(shorty + 1); 176 size_t num_wide_args = std::count(shorty + 1, shorty + 1 + num_args, 'J') + 177 std::count(shorty + 1, shorty + 1 + num_args, 'D'); 178 size_t num_arg_vregs = num_args + num_wide_args + (dex_compilation_unit_->IsStatic() ? 0u : 1u); 179 180 // For simplicity, reserve 2 vregs (the maximum) for return value regardless of the return type. 181 size_t return_vregs = 2u; 182 graph_->SetNumberOfVRegs(return_vregs + num_arg_vregs); 183 graph_->SetNumberOfInVRegs(num_arg_vregs); 184 graph_->SetMaximumNumberOfOutVRegs(num_arg_vregs); 185 graph_->SetHasTryCatch(false); 186 187 // Use ScopedArenaAllocator for all local allocations. 188 ScopedArenaAllocator local_allocator(graph_->GetArenaStack()); 189 HBasicBlockBuilder block_builder(graph_, 190 dex_file_, 191 CodeItemDebugInfoAccessor(), 192 &local_allocator); 193 SsaBuilder ssa_builder(graph_, 194 dex_compilation_unit_->GetClassLoader(), 195 dex_compilation_unit_->GetDexCache(), 196 handles_, 197 &local_allocator); 198 HInstructionBuilder instruction_builder(graph_, 199 &block_builder, 200 &ssa_builder, 201 dex_file_, 202 CodeItemDebugInfoAccessor(), 203 return_type_, 204 dex_compilation_unit_, 205 outer_compilation_unit_, 206 compiler_driver_, 207 code_generator_, 208 interpreter_metadata_, 209 compilation_stats_, 210 handles_, 211 &local_allocator); 212 213 // 1) Create basic blocks for the intrinsic and link them together. 214 block_builder.BuildIntrinsic(); 215 216 // 2) Build the trivial dominator tree. 217 GraphAnalysisResult bdt_result = graph_->BuildDominatorTree(); 218 DCHECK_EQ(bdt_result, kAnalysisSuccess); 219 220 // 3) Populate basic blocks with instructions for the intrinsic. 221 instruction_builder.BuildIntrinsic(method); 222 223 // 4) Type the graph (no dead/redundant phis to eliminate). 224 GraphAnalysisResult build_ssa_result = ssa_builder.BuildSsa(); 225 DCHECK_EQ(build_ssa_result, kAnalysisSuccess); 226 } 227 228 } // namespace art 229