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 <android-base/logging.h> 26 27 #include "base/atomic.h" 28 #include "base/globals.h" 29 30 namespace art { 31 32 enum class MethodCompilationStat { 33 kAttemptBytecodeCompilation = 0, 34 kAttemptIntrinsicCompilation, 35 kCompiledNativeStub, 36 kCompiledIntrinsic, 37 kCompiledBytecode, 38 kCHAInline, 39 kInlinedInvoke, 40 kInlinedLastInvoke, 41 kReplacedInvokeWithSimplePattern, 42 kInstructionSimplifications, 43 kInstructionSimplificationsArch, 44 kUnresolvedMethod, 45 kUnresolvedField, 46 kUnresolvedFieldNotAFastAccess, 47 kRemovedCheckedCast, 48 kRemovedDeadInstruction, 49 kRemovedNullCheck, 50 kNotCompiledSkipped, 51 kNotCompiledInvalidBytecode, 52 kNotCompiledThrowCatchLoop, 53 kNotCompiledAmbiguousArrayOp, 54 kNotCompiledHugeMethod, 55 kNotCompiledLargeMethodNoBranches, 56 kNotCompiledMalformedOpcode, 57 kNotCompiledNoCodegen, 58 kNotCompiledPathological, 59 kNotCompiledSpaceFilter, 60 kNotCompiledUnhandledInstruction, 61 kNotCompiledUnsupportedIsa, 62 kNotCompiledIrreducibleLoopAndStringInit, 63 kNotCompiledPhiEquivalentInOsr, 64 kInlinedMonomorphicCall, 65 kInlinedPolymorphicCall, 66 kMonomorphicCall, 67 kPolymorphicCall, 68 kMegamorphicCall, 69 kBooleanSimplified, 70 kIntrinsicRecognized, 71 kLoopInvariantMoved, 72 kLoopVectorized, 73 kLoopVectorizedIdiom, 74 kSelectGenerated, 75 kRemovedInstanceOf, 76 kInlinedInvokeVirtualOrInterface, 77 kInlinedLastInvokeVirtualOrInterface, 78 kImplicitNullCheckGenerated, 79 kExplicitNullCheckGenerated, 80 kSimplifyIf, 81 kSimplifyThrowingInvoke, 82 kInstructionSunk, 83 kNotInlinedUnresolvedEntrypoint, 84 kNotInlinedBss, 85 kNotInlinedDexCacheInaccessibleToCaller, 86 kNotInlinedDexCacheClinitCheck, 87 kNotInlinedStackMaps, 88 kNotInlinedEnvironmentBudget, 89 kNotInlinedInstructionBudget, 90 kNotInlinedLoopWithoutExit, 91 kNotInlinedIrreducibleLoop, 92 kNotInlinedAlwaysThrows, 93 kNotInlinedInfiniteLoop, 94 kNotInlinedTryCatchCaller, 95 kNotInlinedTryCatchCallee, 96 kNotInlinedRegisterAllocator, 97 kNotInlinedCannotBuild, 98 kNotInlinedNotCompilable, 99 kNotInlinedNotVerified, 100 kNotInlinedCodeItem, 101 kNotInlinedWont, 102 kNotInlinedRecursiveBudget, 103 kNotInlinedPolymorphicRecursiveBudget, 104 kNotInlinedProxy, 105 kNotInlinedUnresolved, 106 kNotInlinedPolymorphic, 107 kNotInlinedCustom, 108 kTryInline, 109 kConstructorFenceGeneratedNew, 110 kConstructorFenceGeneratedFinal, 111 kConstructorFenceRemovedLSE, 112 kConstructorFenceRemovedPFRA, 113 kConstructorFenceRemovedCFRE, 114 kBitstringTypeCheck, 115 kJitOutOfMemoryForCommit, 116 kFullLSEAllocationRemoved, 117 kFullLSEPossible, 118 kNonPartialLoadRemoved, 119 kPartialLSEPossible, 120 kPartialStoreRemoved, 121 kPartialAllocationMoved, 122 kPredicatedLoadAdded, 123 kPredicatedStoreAdded, 124 kDevirtualized, 125 kLastStat 126 }; 127 std::ostream& operator<<(std::ostream& os, MethodCompilationStat rhs); 128 129 class OptimizingCompilerStats { 130 public: OptimizingCompilerStats()131 OptimizingCompilerStats() { 132 // The std::atomic<> default constructor leaves values uninitialized, so initialize them now. 133 Reset(); 134 } 135 136 void RecordStat(MethodCompilationStat stat, uint32_t count = 1) { 137 size_t stat_index = static_cast<size_t>(stat); 138 DCHECK_LT(stat_index, arraysize(compile_stats_)); 139 compile_stats_[stat_index] += count; 140 } 141 GetStat(MethodCompilationStat stat)142 uint32_t GetStat(MethodCompilationStat stat) const { 143 size_t stat_index = static_cast<size_t>(stat); 144 DCHECK_LT(stat_index, arraysize(compile_stats_)); 145 return compile_stats_[stat_index]; 146 } 147 Log()148 void Log() const { 149 uint32_t compiled_intrinsics = GetStat(MethodCompilationStat::kCompiledIntrinsic); 150 uint32_t compiled_native_stubs = GetStat(MethodCompilationStat::kCompiledNativeStub); 151 uint32_t bytecode_attempts = 152 GetStat(MethodCompilationStat::kAttemptBytecodeCompilation); 153 if (compiled_intrinsics == 0u && compiled_native_stubs == 0u && bytecode_attempts == 0u) { 154 LOG(INFO) << "Did not compile any method."; 155 } else { 156 uint32_t compiled_bytecode_methods = 157 GetStat(MethodCompilationStat::kCompiledBytecode); 158 // Successful intrinsic compilation preempts other compilation attempts but failed intrinsic 159 // compilation shall still count towards bytecode or native stub compilation attempts. 160 uint32_t num_compilation_attempts = 161 compiled_intrinsics + compiled_native_stubs + bytecode_attempts; 162 uint32_t num_successful_compilations = 163 compiled_intrinsics + compiled_native_stubs + compiled_bytecode_methods; 164 float compiled_percent = num_successful_compilations * 100.0f / num_compilation_attempts; 165 LOG(INFO) << "Attempted compilation of " 166 << num_compilation_attempts << " methods: " << std::fixed << std::setprecision(2) 167 << compiled_percent << "% (" << num_successful_compilations << ") compiled."; 168 169 for (size_t i = 0; i < arraysize(compile_stats_); ++i) { 170 if (compile_stats_[i] != 0) { 171 LOG(INFO) << "OptStat#" << static_cast<MethodCompilationStat>(i) << ": " 172 << compile_stats_[i]; 173 } 174 } 175 } 176 } 177 AddTo(OptimizingCompilerStats * other_stats)178 void AddTo(OptimizingCompilerStats* other_stats) { 179 for (size_t i = 0; i != arraysize(compile_stats_); ++i) { 180 uint32_t count = compile_stats_[i]; 181 if (count != 0) { 182 other_stats->RecordStat(static_cast<MethodCompilationStat>(i), count); 183 } 184 } 185 } 186 Reset()187 void Reset() { 188 for (std::atomic<uint32_t>& stat : compile_stats_) { 189 stat = 0u; 190 } 191 } 192 193 private: 194 std::atomic<uint32_t> compile_stats_[static_cast<size_t>(MethodCompilationStat::kLastStat)]; 195 196 DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats); 197 }; 198 199 inline void MaybeRecordStat(OptimizingCompilerStats* compiler_stats, 200 MethodCompilationStat stat, 201 uint32_t count = 1) { 202 if (compiler_stats != nullptr) { 203 compiler_stats->RecordStat(stat, count); 204 } 205 } 206 207 } // namespace art 208 209 #endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ 210