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