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 <iomanip>
21 #include <string>
22 #include <type_traits>
23 
24 #include "atomic.h"
25 
26 namespace art {
27 
28 enum MethodCompilationStat {
29   kAttemptCompilation = 0,
30   kCompiled,
31   kInlinedInvoke,
32   kReplacedInvokeWithSimplePattern,
33   kInstructionSimplifications,
34   kInstructionSimplificationsArch,
35   kUnresolvedMethod,
36   kUnresolvedField,
37   kUnresolvedFieldNotAFastAccess,
38   kRemovedCheckedCast,
39   kRemovedDeadInstruction,
40   kRemovedNullCheck,
41   kNotCompiledSkipped,
42   kNotCompiledInvalidBytecode,
43   kNotCompiledThrowCatchLoop,
44   kNotCompiledAmbiguousArrayOp,
45   kNotCompiledHugeMethod,
46   kNotCompiledLargeMethodNoBranches,
47   kNotCompiledMalformedOpcode,
48   kNotCompiledNoCodegen,
49   kNotCompiledPathological,
50   kNotCompiledSpaceFilter,
51   kNotCompiledUnhandledInstruction,
52   kNotCompiledUnsupportedIsa,
53   kNotCompiledVerificationError,
54   kNotCompiledVerifyAtRuntime,
55   kInlinedMonomorphicCall,
56   kInlinedPolymorphicCall,
57   kMonomorphicCall,
58   kPolymorphicCall,
59   kMegamorphicCall,
60   kBooleanSimplified,
61   kIntrinsicRecognized,
62   kLoopInvariantMoved,
63   kSelectGenerated,
64   kRemovedInstanceOf,
65   kInlinedInvokeVirtualOrInterface,
66   kImplicitNullCheckGenerated,
67   kExplicitNullCheckGenerated,
68   kLastStat
69 };
70 
71 class OptimizingCompilerStats {
72  public:
OptimizingCompilerStats()73   OptimizingCompilerStats() {}
74 
75   void RecordStat(MethodCompilationStat stat, size_t count = 1) {
76     compile_stats_[stat] += count;
77   }
78 
Log()79   void Log() const {
80     if (!kIsDebugBuild && !VLOG_IS_ON(compiler)) {
81       // Log only in debug builds or if the compiler is verbose.
82       return;
83     }
84 
85     if (compile_stats_[kAttemptCompilation] == 0) {
86       LOG(INFO) << "Did not compile any method.";
87     } else {
88       float compiled_percent =
89           compile_stats_[kCompiled] * 100.0f / compile_stats_[kAttemptCompilation];
90       LOG(INFO) << "Attempted compilation of " << compile_stats_[kAttemptCompilation]
91           << " methods: " << std::fixed << std::setprecision(2)
92           << compiled_percent << "% (" << compile_stats_[kCompiled] << ") compiled.";
93 
94       for (int i = 0; i < kLastStat; i++) {
95         if (compile_stats_[i] != 0) {
96           LOG(INFO) << PrintMethodCompilationStat(static_cast<MethodCompilationStat>(i)) << ": "
97               << compile_stats_[i];
98         }
99       }
100     }
101   }
102 
103  private:
PrintMethodCompilationStat(MethodCompilationStat stat)104   std::string PrintMethodCompilationStat(MethodCompilationStat stat) const {
105     std::string name;
106     switch (stat) {
107       case kAttemptCompilation : name = "AttemptCompilation"; break;
108       case kCompiled : name = "Compiled"; break;
109       case kInlinedInvoke : name = "InlinedInvoke"; break;
110       case kReplacedInvokeWithSimplePattern: name = "ReplacedInvokeWithSimplePattern"; break;
111       case kInstructionSimplifications: name = "InstructionSimplifications"; break;
112       case kInstructionSimplificationsArch: name = "InstructionSimplificationsArch"; break;
113       case kUnresolvedMethod : name = "UnresolvedMethod"; break;
114       case kUnresolvedField : name = "UnresolvedField"; break;
115       case kUnresolvedFieldNotAFastAccess : name = "UnresolvedFieldNotAFastAccess"; break;
116       case kRemovedCheckedCast: name = "RemovedCheckedCast"; break;
117       case kRemovedDeadInstruction: name = "RemovedDeadInstruction"; break;
118       case kRemovedNullCheck: name = "RemovedNullCheck"; break;
119       case kNotCompiledSkipped: name = "NotCompiledSkipped"; break;
120       case kNotCompiledInvalidBytecode: name = "NotCompiledInvalidBytecode"; break;
121       case kNotCompiledThrowCatchLoop : name = "NotCompiledThrowCatchLoop"; break;
122       case kNotCompiledAmbiguousArrayOp : name = "NotCompiledAmbiguousArrayOp"; break;
123       case kNotCompiledHugeMethod : name = "NotCompiledHugeMethod"; break;
124       case kNotCompiledLargeMethodNoBranches : name = "NotCompiledLargeMethodNoBranches"; break;
125       case kNotCompiledMalformedOpcode : name = "NotCompiledMalformedOpcode"; break;
126       case kNotCompiledNoCodegen : name = "NotCompiledNoCodegen"; break;
127       case kNotCompiledPathological : name = "NotCompiledPathological"; break;
128       case kNotCompiledSpaceFilter : name = "NotCompiledSpaceFilter"; break;
129       case kNotCompiledUnhandledInstruction : name = "NotCompiledUnhandledInstruction"; break;
130       case kNotCompiledUnsupportedIsa : name = "NotCompiledUnsupportedIsa"; break;
131       case kNotCompiledVerificationError : name = "NotCompiledVerificationError"; break;
132       case kNotCompiledVerifyAtRuntime : name = "NotCompiledVerifyAtRuntime"; break;
133       case kInlinedMonomorphicCall: name = "InlinedMonomorphicCall"; break;
134       case kInlinedPolymorphicCall: name = "InlinedPolymorphicCall"; break;
135       case kMonomorphicCall: name = "MonomorphicCall"; break;
136       case kPolymorphicCall: name = "PolymorphicCall"; break;
137       case kMegamorphicCall: name = "MegamorphicCall"; break;
138       case kBooleanSimplified : name = "BooleanSimplified"; break;
139       case kIntrinsicRecognized : name = "IntrinsicRecognized"; break;
140       case kLoopInvariantMoved : name = "LoopInvariantMoved"; break;
141       case kSelectGenerated : name = "SelectGenerated"; break;
142       case kRemovedInstanceOf: name = "RemovedInstanceOf"; break;
143       case kInlinedInvokeVirtualOrInterface: name = "InlinedInvokeVirtualOrInterface"; break;
144       case kImplicitNullCheckGenerated: name = "ImplicitNullCheckGenerated"; break;
145       case kExplicitNullCheckGenerated: name = "ExplicitNullCheckGenerated"; break;
146 
147       case kLastStat:
148         LOG(FATAL) << "invalid stat "
149             << static_cast<std::underlying_type<MethodCompilationStat>::type>(stat);
150         UNREACHABLE();
151     }
152     return "OptStat#" + name;
153   }
154 
155   AtomicInteger compile_stats_[kLastStat];
156 
157   DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats);
158 };
159 
160 }  // namespace art
161 
162 #endif  // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_
163