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