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 kNotCompiledMalformedOpcode, 62 kNotCompiledNoCodegen, 63 kNotCompiledPathological, 64 kNotCompiledSpaceFilter, 65 kNotCompiledUnhandledInstruction, 66 kNotCompiledUnsupportedIsa, 67 kNotCompiledInliningIrreducibleLoop, 68 kNotCompiledIrreducibleLoopAndStringInit, 69 kNotCompiledPhiEquivalentInOsr, 70 kNotCompiledFrameTooBig, 71 kInlinedMonomorphicCall, 72 kInlinedPolymorphicCall, 73 kMonomorphicCall, 74 kPolymorphicCall, 75 kMegamorphicCall, 76 kBooleanSimplified, 77 kIntrinsicRecognized, 78 kLoopInvariantMoved, 79 kLoopVectorized, 80 kLoopVectorizedIdiom, 81 kRemovedInstanceOf, 82 kPropagatedIfValue, 83 kInlinedInvokeVirtualOrInterface, 84 kInlinedLastInvokeVirtualOrInterface, 85 kImplicitNullCheckGenerated, 86 kExplicitNullCheckGenerated, 87 kControlFlowSelectGenerated, 88 kControlFlowDiamondRemoved, 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 kDevirtualized, 135 kLastStat 136 }; 137 std::ostream& operator<<(std::ostream& os, MethodCompilationStat rhs); 138 139 class OptimizingCompilerStats { 140 public: OptimizingCompilerStats()141 OptimizingCompilerStats() { 142 // The std::atomic<> default constructor leaves values uninitialized, so initialize them now. 143 Reset(); 144 } 145 146 void RecordStat(MethodCompilationStat stat, uint32_t count = 1) { 147 size_t stat_index = static_cast<size_t>(stat); 148 DCHECK_LT(stat_index, arraysize(compile_stats_)); 149 compile_stats_[stat_index] += count; 150 } 151 GetStat(MethodCompilationStat stat)152 uint32_t GetStat(MethodCompilationStat stat) const { 153 size_t stat_index = static_cast<size_t>(stat); 154 DCHECK_LT(stat_index, arraysize(compile_stats_)); 155 return compile_stats_[stat_index]; 156 } 157 Log()158 void Log() const { 159 uint32_t compiled_intrinsics = GetStat(MethodCompilationStat::kCompiledIntrinsic); 160 uint32_t compiled_native_stubs = GetStat(MethodCompilationStat::kCompiledNativeStub); 161 uint32_t bytecode_attempts = 162 GetStat(MethodCompilationStat::kAttemptBytecodeCompilation); 163 if (compiled_intrinsics == 0u && compiled_native_stubs == 0u && bytecode_attempts == 0u) { 164 LOG(INFO) << "Did not compile any method."; 165 } else { 166 uint32_t compiled_bytecode_methods = 167 GetStat(MethodCompilationStat::kCompiledBytecode); 168 // Successful intrinsic compilation preempts other compilation attempts but failed intrinsic 169 // compilation shall still count towards bytecode or native stub compilation attempts. 170 uint32_t num_compilation_attempts = 171 compiled_intrinsics + compiled_native_stubs + bytecode_attempts; 172 uint32_t num_successful_compilations = 173 compiled_intrinsics + compiled_native_stubs + compiled_bytecode_methods; 174 float compiled_percent = num_successful_compilations * 100.0f / num_compilation_attempts; 175 LOG(INFO) << "Attempted compilation of " 176 << num_compilation_attempts << " methods: " << std::fixed << std::setprecision(2) 177 << compiled_percent << "% (" << num_successful_compilations << ") compiled."; 178 179 for (size_t i = 0; i < arraysize(compile_stats_); ++i) { 180 if (compile_stats_[i] != 0) { 181 LOG(INFO) << "OptStat#" << static_cast<MethodCompilationStat>(i) << ": " 182 << compile_stats_[i]; 183 } 184 } 185 } 186 } 187 AddTo(OptimizingCompilerStats * other_stats)188 void AddTo(OptimizingCompilerStats* other_stats) { 189 for (size_t i = 0; i != arraysize(compile_stats_); ++i) { 190 uint32_t count = compile_stats_[i]; 191 if (count != 0) { 192 other_stats->RecordStat(static_cast<MethodCompilationStat>(i), count); 193 } 194 } 195 } 196 Reset()197 void Reset() { 198 for (std::atomic<uint32_t>& stat : compile_stats_) { 199 stat = 0u; 200 } 201 } 202 203 private: 204 std::atomic<uint32_t> compile_stats_[static_cast<size_t>(MethodCompilationStat::kLastStat)]; 205 206 DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats); 207 }; 208 209 inline void MaybeRecordStat(OptimizingCompilerStats* compiler_stats, 210 MethodCompilationStat stat, 211 uint32_t count = 1) { 212 if (compiler_stats != nullptr) { 213 compiler_stats->RecordStat(stat, count); 214 } 215 } 216 217 } // namespace art 218 219 #endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ 220