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