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 kFullLSEAllocationRemoved, 112 kFullLSEPossible, 113 kNonPartialLoadRemoved, 114 kPartialLSEPossible, 115 kPartialStoreRemoved, 116 kPartialAllocationMoved, 117 kPredicatedLoadAdded, 118 kPredicatedStoreAdded, 119 kDevirtualized, 120 kLastStat 121 }; 122 std::ostream& operator<<(std::ostream& os, MethodCompilationStat rhs); 123 124 class OptimizingCompilerStats { 125 public: OptimizingCompilerStats()126 OptimizingCompilerStats() { 127 // The std::atomic<> default constructor leaves values uninitialized, so initialize them now. 128 Reset(); 129 } 130 131 void RecordStat(MethodCompilationStat stat, uint32_t count = 1) { 132 size_t stat_index = static_cast<size_t>(stat); 133 DCHECK_LT(stat_index, arraysize(compile_stats_)); 134 compile_stats_[stat_index] += count; 135 } 136 GetStat(MethodCompilationStat stat)137 uint32_t GetStat(MethodCompilationStat stat) const { 138 size_t stat_index = static_cast<size_t>(stat); 139 DCHECK_LT(stat_index, arraysize(compile_stats_)); 140 return compile_stats_[stat_index]; 141 } 142 Log()143 void Log() const { 144 uint32_t compiled_intrinsics = GetStat(MethodCompilationStat::kCompiledIntrinsic); 145 uint32_t compiled_native_stubs = GetStat(MethodCompilationStat::kCompiledNativeStub); 146 uint32_t bytecode_attempts = 147 GetStat(MethodCompilationStat::kAttemptBytecodeCompilation); 148 if (compiled_intrinsics == 0u && compiled_native_stubs == 0u && bytecode_attempts == 0u) { 149 LOG(INFO) << "Did not compile any method."; 150 } else { 151 uint32_t compiled_bytecode_methods = 152 GetStat(MethodCompilationStat::kCompiledBytecode); 153 // Successful intrinsic compilation preempts other compilation attempts but failed intrinsic 154 // compilation shall still count towards bytecode or native stub compilation attempts. 155 uint32_t num_compilation_attempts = 156 compiled_intrinsics + compiled_native_stubs + bytecode_attempts; 157 uint32_t num_successful_compilations = 158 compiled_intrinsics + compiled_native_stubs + compiled_bytecode_methods; 159 float compiled_percent = num_successful_compilations * 100.0f / num_compilation_attempts; 160 LOG(INFO) << "Attempted compilation of " 161 << num_compilation_attempts << " methods: " << std::fixed << std::setprecision(2) 162 << compiled_percent << "% (" << num_successful_compilations << ") compiled."; 163 164 for (size_t i = 0; i < arraysize(compile_stats_); ++i) { 165 if (compile_stats_[i] != 0) { 166 LOG(INFO) << "OptStat#" << static_cast<MethodCompilationStat>(i) << ": " 167 << compile_stats_[i]; 168 } 169 } 170 } 171 } 172 AddTo(OptimizingCompilerStats * other_stats)173 void AddTo(OptimizingCompilerStats* other_stats) { 174 for (size_t i = 0; i != arraysize(compile_stats_); ++i) { 175 uint32_t count = compile_stats_[i]; 176 if (count != 0) { 177 other_stats->RecordStat(static_cast<MethodCompilationStat>(i), count); 178 } 179 } 180 } 181 Reset()182 void Reset() { 183 for (std::atomic<uint32_t>& stat : compile_stats_) { 184 stat = 0u; 185 } 186 } 187 188 private: 189 std::atomic<uint32_t> compile_stats_[static_cast<size_t>(MethodCompilationStat::kLastStat)]; 190 191 DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats); 192 }; 193 194 inline void MaybeRecordStat(OptimizingCompilerStats* compiler_stats, 195 MethodCompilationStat stat, 196 uint32_t count = 1) { 197 if (compiler_stats != nullptr) { 198 compiler_stats->RecordStat(stat, count); 199 } 200 } 201 202 } // namespace art 203 204 #endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ 205