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