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