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 #ifndef ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ 18 #define ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ 19 20 #include <atomic> 21 #include <iomanip> 22 #include <string> 23 #include <type_traits> 24 25 #include "atomic.h" 26 27 namespace art { 28 29 enum MethodCompilationStat { 30 kAttemptCompilation = 0, 31 kCHAInline, 32 kCompiled, 33 kInlinedInvoke, 34 kReplacedInvokeWithSimplePattern, 35 kInstructionSimplifications, 36 kInstructionSimplificationsArch, 37 kUnresolvedMethod, 38 kUnresolvedField, 39 kUnresolvedFieldNotAFastAccess, 40 kRemovedCheckedCast, 41 kRemovedDeadInstruction, 42 kRemovedNullCheck, 43 kNotCompiledSkipped, 44 kNotCompiledInvalidBytecode, 45 kNotCompiledThrowCatchLoop, 46 kNotCompiledAmbiguousArrayOp, 47 kNotCompiledHugeMethod, 48 kNotCompiledLargeMethodNoBranches, 49 kNotCompiledMalformedOpcode, 50 kNotCompiledNoCodegen, 51 kNotCompiledPathological, 52 kNotCompiledSpaceFilter, 53 kNotCompiledUnhandledInstruction, 54 kNotCompiledUnsupportedIsa, 55 kNotCompiledVerificationError, 56 kNotCompiledVerifyAtRuntime, 57 kInlinedMonomorphicCall, 58 kInlinedPolymorphicCall, 59 kMonomorphicCall, 60 kPolymorphicCall, 61 kMegamorphicCall, 62 kBooleanSimplified, 63 kIntrinsicRecognized, 64 kLoopInvariantMoved, 65 kSelectGenerated, 66 kRemovedInstanceOf, 67 kInlinedInvokeVirtualOrInterface, 68 kImplicitNullCheckGenerated, 69 kExplicitNullCheckGenerated, 70 kSimplifyIf, 71 kInstructionSunk, 72 kNotInlinedUnresolvedEntrypoint, 73 kNotInlinedDexCache, 74 kNotInlinedStackMaps, 75 kNotInlinedEnvironmentBudget, 76 kNotInlinedInstructionBudget, 77 kNotInlinedLoopWithoutExit, 78 kNotInlinedIrreducibleLoop, 79 kNotInlinedAlwaysThrows, 80 kNotInlinedInfiniteLoop, 81 kNotInlinedTryCatch, 82 kNotInlinedRegisterAllocator, 83 kNotInlinedCannotBuild, 84 kNotInlinedNotVerified, 85 kNotInlinedCodeItem, 86 kNotInlinedWont, 87 kNotInlinedRecursiveBudget, 88 kNotInlinedProxy, 89 kLastStat 90 }; 91 92 class OptimizingCompilerStats { 93 public: OptimizingCompilerStats()94 OptimizingCompilerStats() { 95 // The std::atomic<> default constructor leaves values uninitialized, so initialize them now. 96 Reset(); 97 } 98 99 void RecordStat(MethodCompilationStat stat, uint32_t count = 1) { 100 compile_stats_[stat] += count; 101 } 102 Log()103 void Log() const { 104 if (!kIsDebugBuild && !VLOG_IS_ON(compiler)) { 105 // Log only in debug builds or if the compiler is verbose. 106 return; 107 } 108 109 if (compile_stats_[kAttemptCompilation] == 0) { 110 LOG(INFO) << "Did not compile any method."; 111 } else { 112 float compiled_percent = 113 compile_stats_[kCompiled] * 100.0f / compile_stats_[kAttemptCompilation]; 114 LOG(INFO) << "Attempted compilation of " << compile_stats_[kAttemptCompilation] 115 << " methods: " << std::fixed << std::setprecision(2) 116 << compiled_percent << "% (" << compile_stats_[kCompiled] << ") compiled."; 117 118 for (size_t i = 0; i < kLastStat; i++) { 119 if (compile_stats_[i] != 0) { 120 LOG(INFO) << PrintMethodCompilationStat(static_cast<MethodCompilationStat>(i)) << ": " 121 << compile_stats_[i]; 122 } 123 } 124 } 125 } 126 AddTo(OptimizingCompilerStats * other_stats)127 void AddTo(OptimizingCompilerStats* other_stats) { 128 for (size_t i = 0; i != kLastStat; ++i) { 129 uint32_t count = compile_stats_[i]; 130 if (count != 0) { 131 other_stats->RecordStat(static_cast<MethodCompilationStat>(i), count); 132 } 133 } 134 } 135 Reset()136 void Reset() { 137 for (size_t i = 0; i != kLastStat; ++i) { 138 compile_stats_[i] = 0u; 139 } 140 } 141 142 private: PrintMethodCompilationStat(MethodCompilationStat stat)143 std::string PrintMethodCompilationStat(MethodCompilationStat stat) const { 144 std::string name; 145 switch (stat) { 146 case kAttemptCompilation : name = "AttemptCompilation"; break; 147 case kCHAInline : name = "CHAInline"; break; 148 case kCompiled : name = "Compiled"; break; 149 case kInlinedInvoke : name = "InlinedInvoke"; break; 150 case kReplacedInvokeWithSimplePattern: name = "ReplacedInvokeWithSimplePattern"; break; 151 case kInstructionSimplifications: name = "InstructionSimplifications"; break; 152 case kInstructionSimplificationsArch: name = "InstructionSimplificationsArch"; break; 153 case kUnresolvedMethod : name = "UnresolvedMethod"; break; 154 case kUnresolvedField : name = "UnresolvedField"; break; 155 case kUnresolvedFieldNotAFastAccess : name = "UnresolvedFieldNotAFastAccess"; break; 156 case kRemovedCheckedCast: name = "RemovedCheckedCast"; break; 157 case kRemovedDeadInstruction: name = "RemovedDeadInstruction"; break; 158 case kRemovedNullCheck: name = "RemovedNullCheck"; break; 159 case kNotCompiledSkipped: name = "NotCompiledSkipped"; break; 160 case kNotCompiledInvalidBytecode: name = "NotCompiledInvalidBytecode"; break; 161 case kNotCompiledThrowCatchLoop : name = "NotCompiledThrowCatchLoop"; break; 162 case kNotCompiledAmbiguousArrayOp : name = "NotCompiledAmbiguousArrayOp"; break; 163 case kNotCompiledHugeMethod : name = "NotCompiledHugeMethod"; break; 164 case kNotCompiledLargeMethodNoBranches : name = "NotCompiledLargeMethodNoBranches"; break; 165 case kNotCompiledMalformedOpcode : name = "NotCompiledMalformedOpcode"; break; 166 case kNotCompiledNoCodegen : name = "NotCompiledNoCodegen"; break; 167 case kNotCompiledPathological : name = "NotCompiledPathological"; break; 168 case kNotCompiledSpaceFilter : name = "NotCompiledSpaceFilter"; break; 169 case kNotCompiledUnhandledInstruction : name = "NotCompiledUnhandledInstruction"; break; 170 case kNotCompiledUnsupportedIsa : name = "NotCompiledUnsupportedIsa"; break; 171 case kNotCompiledVerificationError : name = "NotCompiledVerificationError"; break; 172 case kNotCompiledVerifyAtRuntime : name = "NotCompiledVerifyAtRuntime"; break; 173 case kInlinedMonomorphicCall: name = "InlinedMonomorphicCall"; break; 174 case kInlinedPolymorphicCall: name = "InlinedPolymorphicCall"; break; 175 case kMonomorphicCall: name = "MonomorphicCall"; break; 176 case kPolymorphicCall: name = "PolymorphicCall"; break; 177 case kMegamorphicCall: name = "MegamorphicCall"; break; 178 case kBooleanSimplified : name = "BooleanSimplified"; break; 179 case kIntrinsicRecognized : name = "IntrinsicRecognized"; break; 180 case kLoopInvariantMoved : name = "LoopInvariantMoved"; break; 181 case kSelectGenerated : name = "SelectGenerated"; break; 182 case kRemovedInstanceOf: name = "RemovedInstanceOf"; break; 183 case kInlinedInvokeVirtualOrInterface: name = "InlinedInvokeVirtualOrInterface"; break; 184 case kImplicitNullCheckGenerated: name = "ImplicitNullCheckGenerated"; break; 185 case kExplicitNullCheckGenerated: name = "ExplicitNullCheckGenerated"; break; 186 case kSimplifyIf: name = "SimplifyIf"; break; 187 case kInstructionSunk: name = "InstructionSunk"; break; 188 case kNotInlinedUnresolvedEntrypoint: name = "NotInlinedUnresolvedEntrypoint"; break; 189 case kNotInlinedDexCache: name = "NotInlinedDexCache"; break; 190 case kNotInlinedStackMaps: name = "NotInlinedStackMaps"; break; 191 case kNotInlinedEnvironmentBudget: name = "NotInlinedEnvironmentBudget"; break; 192 case kNotInlinedInstructionBudget: name = "NotInlinedInstructionBudget"; break; 193 case kNotInlinedLoopWithoutExit: name = "NotInlinedLoopWithoutExit"; break; 194 case kNotInlinedIrreducibleLoop: name = "NotInlinedIrreducibleLoop"; break; 195 case kNotInlinedAlwaysThrows: name = "NotInlinedAlwaysThrows"; break; 196 case kNotInlinedInfiniteLoop: name = "NotInlinedInfiniteLoop"; break; 197 case kNotInlinedTryCatch: name = "NotInlinedTryCatch"; break; 198 case kNotInlinedRegisterAllocator: name = "NotInlinedRegisterAllocator"; break; 199 case kNotInlinedCannotBuild: name = "NotInlinedCannotBuild"; break; 200 case kNotInlinedNotVerified: name = "NotInlinedNotVerified"; break; 201 case kNotInlinedCodeItem: name = "NotInlinedCodeItem"; break; 202 case kNotInlinedWont: name = "NotInlinedWont"; break; 203 case kNotInlinedRecursiveBudget: name = "NotInlinedRecursiveBudget"; break; 204 case kNotInlinedProxy: name = "NotInlinedProxy"; break; 205 206 case kLastStat: 207 LOG(FATAL) << "invalid stat " 208 << static_cast<std::underlying_type<MethodCompilationStat>::type>(stat); 209 UNREACHABLE(); 210 } 211 return "OptStat#" + name; 212 } 213 214 std::atomic<uint32_t> compile_stats_[kLastStat]; 215 216 DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats); 217 }; 218 219 } // namespace art 220 221 #endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ 222