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 "atomic.h"
26 
27 namespace art {
28 
29 enum MethodCompilationStat {
30   kAttemptCompilation = 0,
31   kCHAInline,
32   kCompiled,
33   kInlinedInvoke,
34   kReplacedInvokeWithSimplePattern,
35   kInstructionSimplifications,
36   kInstructionSimplificationsArch,
37   kUnresolvedMethod,
38   kUnresolvedField,
39   kUnresolvedFieldNotAFastAccess,
40   kRemovedCheckedCast,
41   kRemovedDeadInstruction,
42   kRemovedNullCheck,
43   kNotCompiledSkipped,
44   kNotCompiledInvalidBytecode,
45   kNotCompiledThrowCatchLoop,
46   kNotCompiledAmbiguousArrayOp,
47   kNotCompiledHugeMethod,
48   kNotCompiledLargeMethodNoBranches,
49   kNotCompiledMalformedOpcode,
50   kNotCompiledNoCodegen,
51   kNotCompiledPathological,
52   kNotCompiledSpaceFilter,
53   kNotCompiledUnhandledInstruction,
54   kNotCompiledUnsupportedIsa,
55   kNotCompiledVerificationError,
56   kNotCompiledVerifyAtRuntime,
57   kInlinedMonomorphicCall,
58   kInlinedPolymorphicCall,
59   kMonomorphicCall,
60   kPolymorphicCall,
61   kMegamorphicCall,
62   kBooleanSimplified,
63   kIntrinsicRecognized,
64   kLoopInvariantMoved,
65   kSelectGenerated,
66   kRemovedInstanceOf,
67   kInlinedInvokeVirtualOrInterface,
68   kImplicitNullCheckGenerated,
69   kExplicitNullCheckGenerated,
70   kSimplifyIf,
71   kInstructionSunk,
72   kNotInlinedUnresolvedEntrypoint,
73   kNotInlinedDexCache,
74   kNotInlinedStackMaps,
75   kNotInlinedEnvironmentBudget,
76   kNotInlinedInstructionBudget,
77   kNotInlinedLoopWithoutExit,
78   kNotInlinedIrreducibleLoop,
79   kNotInlinedAlwaysThrows,
80   kNotInlinedInfiniteLoop,
81   kNotInlinedTryCatch,
82   kNotInlinedRegisterAllocator,
83   kNotInlinedCannotBuild,
84   kNotInlinedNotVerified,
85   kNotInlinedCodeItem,
86   kNotInlinedWont,
87   kNotInlinedRecursiveBudget,
88   kNotInlinedProxy,
89   kLastStat
90 };
91 
92 class OptimizingCompilerStats {
93  public:
OptimizingCompilerStats()94   OptimizingCompilerStats() {
95     // The std::atomic<> default constructor leaves values uninitialized, so initialize them now.
96     Reset();
97   }
98 
99   void RecordStat(MethodCompilationStat stat, uint32_t count = 1) {
100     compile_stats_[stat] += count;
101   }
102 
Log()103   void Log() const {
104     if (!kIsDebugBuild && !VLOG_IS_ON(compiler)) {
105       // Log only in debug builds or if the compiler is verbose.
106       return;
107     }
108 
109     if (compile_stats_[kAttemptCompilation] == 0) {
110       LOG(INFO) << "Did not compile any method.";
111     } else {
112       float compiled_percent =
113           compile_stats_[kCompiled] * 100.0f / compile_stats_[kAttemptCompilation];
114       LOG(INFO) << "Attempted compilation of " << compile_stats_[kAttemptCompilation]
115           << " methods: " << std::fixed << std::setprecision(2)
116           << compiled_percent << "% (" << compile_stats_[kCompiled] << ") compiled.";
117 
118       for (size_t i = 0; i < kLastStat; i++) {
119         if (compile_stats_[i] != 0) {
120           LOG(INFO) << PrintMethodCompilationStat(static_cast<MethodCompilationStat>(i)) << ": "
121               << compile_stats_[i];
122         }
123       }
124     }
125   }
126 
AddTo(OptimizingCompilerStats * other_stats)127   void AddTo(OptimizingCompilerStats* other_stats) {
128     for (size_t i = 0; i != kLastStat; ++i) {
129       uint32_t count = compile_stats_[i];
130       if (count != 0) {
131         other_stats->RecordStat(static_cast<MethodCompilationStat>(i), count);
132       }
133     }
134   }
135 
Reset()136   void Reset() {
137     for (size_t i = 0; i != kLastStat; ++i) {
138       compile_stats_[i] = 0u;
139     }
140   }
141 
142  private:
PrintMethodCompilationStat(MethodCompilationStat stat)143   std::string PrintMethodCompilationStat(MethodCompilationStat stat) const {
144     std::string name;
145     switch (stat) {
146       case kAttemptCompilation : name = "AttemptCompilation"; break;
147       case kCHAInline : name = "CHAInline"; break;
148       case kCompiled : name = "Compiled"; break;
149       case kInlinedInvoke : name = "InlinedInvoke"; break;
150       case kReplacedInvokeWithSimplePattern: name = "ReplacedInvokeWithSimplePattern"; break;
151       case kInstructionSimplifications: name = "InstructionSimplifications"; break;
152       case kInstructionSimplificationsArch: name = "InstructionSimplificationsArch"; break;
153       case kUnresolvedMethod : name = "UnresolvedMethod"; break;
154       case kUnresolvedField : name = "UnresolvedField"; break;
155       case kUnresolvedFieldNotAFastAccess : name = "UnresolvedFieldNotAFastAccess"; break;
156       case kRemovedCheckedCast: name = "RemovedCheckedCast"; break;
157       case kRemovedDeadInstruction: name = "RemovedDeadInstruction"; break;
158       case kRemovedNullCheck: name = "RemovedNullCheck"; break;
159       case kNotCompiledSkipped: name = "NotCompiledSkipped"; break;
160       case kNotCompiledInvalidBytecode: name = "NotCompiledInvalidBytecode"; break;
161       case kNotCompiledThrowCatchLoop : name = "NotCompiledThrowCatchLoop"; break;
162       case kNotCompiledAmbiguousArrayOp : name = "NotCompiledAmbiguousArrayOp"; break;
163       case kNotCompiledHugeMethod : name = "NotCompiledHugeMethod"; break;
164       case kNotCompiledLargeMethodNoBranches : name = "NotCompiledLargeMethodNoBranches"; break;
165       case kNotCompiledMalformedOpcode : name = "NotCompiledMalformedOpcode"; break;
166       case kNotCompiledNoCodegen : name = "NotCompiledNoCodegen"; break;
167       case kNotCompiledPathological : name = "NotCompiledPathological"; break;
168       case kNotCompiledSpaceFilter : name = "NotCompiledSpaceFilter"; break;
169       case kNotCompiledUnhandledInstruction : name = "NotCompiledUnhandledInstruction"; break;
170       case kNotCompiledUnsupportedIsa : name = "NotCompiledUnsupportedIsa"; break;
171       case kNotCompiledVerificationError : name = "NotCompiledVerificationError"; break;
172       case kNotCompiledVerifyAtRuntime : name = "NotCompiledVerifyAtRuntime"; break;
173       case kInlinedMonomorphicCall: name = "InlinedMonomorphicCall"; break;
174       case kInlinedPolymorphicCall: name = "InlinedPolymorphicCall"; break;
175       case kMonomorphicCall: name = "MonomorphicCall"; break;
176       case kPolymorphicCall: name = "PolymorphicCall"; break;
177       case kMegamorphicCall: name = "MegamorphicCall"; break;
178       case kBooleanSimplified : name = "BooleanSimplified"; break;
179       case kIntrinsicRecognized : name = "IntrinsicRecognized"; break;
180       case kLoopInvariantMoved : name = "LoopInvariantMoved"; break;
181       case kSelectGenerated : name = "SelectGenerated"; break;
182       case kRemovedInstanceOf: name = "RemovedInstanceOf"; break;
183       case kInlinedInvokeVirtualOrInterface: name = "InlinedInvokeVirtualOrInterface"; break;
184       case kImplicitNullCheckGenerated: name = "ImplicitNullCheckGenerated"; break;
185       case kExplicitNullCheckGenerated: name = "ExplicitNullCheckGenerated"; break;
186       case kSimplifyIf: name = "SimplifyIf"; break;
187       case kInstructionSunk: name = "InstructionSunk"; break;
188       case kNotInlinedUnresolvedEntrypoint: name = "NotInlinedUnresolvedEntrypoint"; break;
189       case kNotInlinedDexCache: name = "NotInlinedDexCache"; break;
190       case kNotInlinedStackMaps: name = "NotInlinedStackMaps"; break;
191       case kNotInlinedEnvironmentBudget: name = "NotInlinedEnvironmentBudget"; break;
192       case kNotInlinedInstructionBudget: name = "NotInlinedInstructionBudget"; break;
193       case kNotInlinedLoopWithoutExit: name = "NotInlinedLoopWithoutExit"; break;
194       case kNotInlinedIrreducibleLoop: name = "NotInlinedIrreducibleLoop"; break;
195       case kNotInlinedAlwaysThrows: name = "NotInlinedAlwaysThrows"; break;
196       case kNotInlinedInfiniteLoop: name = "NotInlinedInfiniteLoop"; break;
197       case kNotInlinedTryCatch: name = "NotInlinedTryCatch"; break;
198       case kNotInlinedRegisterAllocator: name = "NotInlinedRegisterAllocator"; break;
199       case kNotInlinedCannotBuild: name = "NotInlinedCannotBuild"; break;
200       case kNotInlinedNotVerified: name = "NotInlinedNotVerified"; break;
201       case kNotInlinedCodeItem: name = "NotInlinedCodeItem"; break;
202       case kNotInlinedWont: name = "NotInlinedWont"; break;
203       case kNotInlinedRecursiveBudget: name = "NotInlinedRecursiveBudget"; break;
204       case kNotInlinedProxy: name = "NotInlinedProxy"; break;
205 
206       case kLastStat:
207         LOG(FATAL) << "invalid stat "
208             << static_cast<std::underlying_type<MethodCompilationStat>::type>(stat);
209         UNREACHABLE();
210     }
211     return "OptStat#" + name;
212   }
213 
214   std::atomic<uint32_t> compile_stats_[kLastStat];
215 
216   DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats);
217 };
218 
219 }  // namespace art
220 
221 #endif  // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_
222