148c2b03965830c73cdddeae8aea8030f08430137Calin Juravle/*
248c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * Copyright (C) 2014 The Android Open Source Project
348c2b03965830c73cdddeae8aea8030f08430137Calin Juravle *
448c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * Licensed under the Apache License, Version 2.0 (the "License");
548c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * you may not use this file except in compliance with the License.
648c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * You may obtain a copy of the License at
748c2b03965830c73cdddeae8aea8030f08430137Calin Juravle *
848c2b03965830c73cdddeae8aea8030f08430137Calin Juravle *      http://www.apache.org/licenses/LICENSE-2.0
948c2b03965830c73cdddeae8aea8030f08430137Calin Juravle *
1048c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * Unless required by applicable law or agreed to in writing, software
1148c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * distributed under the License is distributed on an "AS IS" BASIS,
1248c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1348c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * See the License for the specific language governing permissions and
1448c2b03965830c73cdddeae8aea8030f08430137Calin Juravle * limitations under the License.
1548c2b03965830c73cdddeae8aea8030f08430137Calin Juravle */
1648c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
1748c2b03965830c73cdddeae8aea8030f08430137Calin Juravle#ifndef ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_
1848c2b03965830c73cdddeae8aea8030f08430137Calin Juravle#define ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_
1948c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
20438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko#include <atomic>
21ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle#include <iomanip>
2248c2b03965830c73cdddeae8aea8030f08430137Calin Juravle#include <string>
23da9badb9edea5e0d18cd9f97eff0d0937ad48310Andreas Gampe#include <type_traits>
2448c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
258f4b056427a9d2321e3aa4f21ca8ffb18b3e5ae6David Sehr#include "base/atomic.h"
268f4b056427a9d2321e3aa4f21ca8ffb18b3e5ae6David Sehr#include "base/globals.h"
2757943810cfc789da890d73621741729da5feaaf8Andreas Gampe#include "base/logging.h"  // For VLOG_IS_ON.
2848c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
2948c2b03965830c73cdddeae8aea8030f08430137Calin Juravlenamespace art {
3048c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
31cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Markoenum class MethodCompilationStat {
32cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  kAttemptBytecodeCompilation = 0,
33cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  kAttemptIntrinsicCompilation,
34cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  kCompiledNativeStub,
35cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  kCompiledIntrinsic,
36cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  kCompiledBytecode,
37063fc772b5b8aed7d769cd7cccb6ddc7619326eeMingyao Yang  kCHAInline,
38e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  kInlinedInvoke,
39be10e8e99a78caae01fb65769218800d465144aeVladimir Marko  kReplacedInvokeWithSimplePattern,
40702d26018769f9fbc4763c7ed02331aed596ac7dCalin Juravle  kInstructionSimplifications,
4144b9cf937836bb33139123e15ca8b586b5853268Alexandre Rames  kInstructionSimplificationsArch,
42175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  kUnresolvedMethod,
43e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  kUnresolvedField,
4407380a2d6cb9feee02facc81f699eed5cb670cd5Calin Juravle  kUnresolvedFieldNotAFastAccess,
45ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle  kRemovedCheckedCast,
46ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle  kRemovedDeadInstruction,
47ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle  kRemovedNullCheck,
4886ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  kNotCompiledSkipped,
4986ea7eeabe30c98bbe1651a51d03cb89776724e7David Brazdil  kNotCompiledInvalidBytecode,
504833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil  kNotCompiledThrowCatchLoop,
5115693bfdf9fa3ec79327a77b7e10315614d716ccDavid Brazdil  kNotCompiledAmbiguousArrayOp,
5248c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  kNotCompiledHugeMethod,
5348c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  kNotCompiledLargeMethodNoBranches,
542e33525bd4eb892246b4c244c6d4ebf6c6d07501Nicolas Geoffray  kNotCompiledMalformedOpcode,
5548c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  kNotCompiledNoCodegen,
56702d26018769f9fbc4763c7ed02331aed596ac7dCalin Juravle  kNotCompiledPathological,
5736540cb4d549c706cc7cd23086684f1548a91042Nicolas Geoffray  kNotCompiledSpaceFilter,
5848c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  kNotCompiledUnhandledInstruction,
59702d26018769f9fbc4763c7ed02331aed596ac7dCalin Juravle  kNotCompiledUnsupportedIsa,
60ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle  kNotCompiledVerificationError,
61f1c6d9e87cbfd27702103ccc7c7f08ce784dc872Calin Juravle  kNotCompiledVerifyAtRuntime,
6273be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray  kInlinedMonomorphicCall,
63a42363f79832a6e14f348514664dc6dc3edf9da2Nicolas Geoffray  kInlinedPolymorphicCall,
6473be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray  kMonomorphicCall,
6573be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray  kPolymorphicCall,
6673be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray  kMegamorphicCall,
6738e9e8046ea2196284bdb4638771c31108a30a4aJean-Philippe Halimi  kBooleanSimplified,
6838e9e8046ea2196284bdb4638771c31108a30a4aJean-Philippe Halimi  kIntrinsicRecognized,
6938e9e8046ea2196284bdb4638771c31108a30a4aJean-Philippe Halimi  kLoopInvariantMoved,
7021b859210d690d25563423eeed5fd630023d23ccAart Bik  kLoopVectorized,
7121b859210d690d25563423eeed5fd630023d23ccAart Bik  kLoopVectorizedIdiom,
7238e9e8046ea2196284bdb4638771c31108a30a4aJean-Philippe Halimi  kSelectGenerated,
736915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle  kRemovedInstanceOf,
746915898b28cea6c9836ca1be6814d87e89cc6d76Calin Juravle  kInlinedInvokeVirtualOrInterface,
752ae48182573da7087bffc2873730bc758ec29696Calin Juravle  kImplicitNullCheckGenerated,
762ae48182573da7087bffc2873730bc758ec29696Calin Juravle  kExplicitNullCheckGenerated,
77dac9b19b822e6cc6f1d7f40e27780515d1fddf22Nicolas Geoffray  kSimplifyIf,
78a8b8e9b12a9740d71cff2fa65d47825b74f72c37Aart Bik  kSimplifyThrowingInvoke,
79b813ca14be33f7db8b7049c3b08a1eb776f25d1bNicolas Geoffray  kInstructionSunk,
80f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedUnresolvedEntrypoint,
81f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedDexCache,
82f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedStackMaps,
83f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedEnvironmentBudget,
84f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedInstructionBudget,
85f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedLoopWithoutExit,
86f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedIrreducibleLoop,
87f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedAlwaysThrows,
88f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedInfiniteLoop,
89f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedTryCatch,
90f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedRegisterAllocator,
91f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedCannotBuild,
92f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedNotVerified,
93f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedCodeItem,
94f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedWont,
95f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedRecursiveBudget,
96f6d4668c42933e2f85ddbc94e276c49db4e2b1ddNicolas Geoffray  kNotInlinedProxy,
976ef45677305048c2bf0600f1c4b98a11b2cfaffbIgor Murashkin  kConstructorFenceGeneratedNew,
986ef45677305048c2bf0600f1c4b98a11b2cfaffbIgor Murashkin  kConstructorFenceGeneratedFinal,
996ef45677305048c2bf0600f1c4b98a11b2cfaffbIgor Murashkin  kConstructorFenceRemovedLSE,
1006ef45677305048c2bf0600f1c4b98a11b2cfaffbIgor Murashkin  kConstructorFenceRemovedPFRA,
101dd018df8a00e841fe38fabe38520b7d297a885c1Igor Murashkin  kConstructorFenceRemovedCFRE,
102cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  kJitOutOfMemoryForCommit,
10348c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  kLastStat
10448c2b03965830c73cdddeae8aea8030f08430137Calin Juravle};
105cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Markostd::ostream& operator<<(std::ostream& os, const MethodCompilationStat& rhs);
10648c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
10748c2b03965830c73cdddeae8aea8030f08430137Calin Juravleclass OptimizingCompilerStats {
10848c2b03965830c73cdddeae8aea8030f08430137Calin Juravle public:
109ff754d19946de43bfd2fc04adcd430459cac1f16Vladimir Marko  OptimizingCompilerStats() {
110ff754d19946de43bfd2fc04adcd430459cac1f16Vladimir Marko    // The std::atomic<> default constructor leaves values uninitialized, so initialize them now.
111ff754d19946de43bfd2fc04adcd430459cac1f16Vladimir Marko    Reset();
112ff754d19946de43bfd2fc04adcd430459cac1f16Vladimir Marko  }
11348c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
114438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko  void RecordStat(MethodCompilationStat stat, uint32_t count = 1) {
115cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    size_t stat_index = static_cast<size_t>(stat);
116cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    DCHECK_LT(stat_index, arraysize(compile_stats_));
117cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    compile_stats_[stat_index] += count;
118cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  }
119cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko
120cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  uint32_t GetStat(MethodCompilationStat stat) const {
121cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    size_t stat_index = static_cast<size_t>(stat);
122cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    DCHECK_LT(stat_index, arraysize(compile_stats_));
123cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    return compile_stats_[stat_index];
12448c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  }
12548c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
12648c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  void Log() const {
127ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle    if (!kIsDebugBuild && !VLOG_IS_ON(compiler)) {
128ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle      // Log only in debug builds or if the compiler is verbose.
129ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle      return;
130ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle    }
131ad543383b5883d6e32993efaefc704eff3225ffeCalin Juravle
132cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    uint32_t compiled_intrinsics = GetStat(MethodCompilationStat::kCompiledIntrinsic);
133cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    uint32_t compiled_native_stubs = GetStat(MethodCompilationStat::kCompiledNativeStub);
134cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    uint32_t bytecode_attempts =
135cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko        GetStat(MethodCompilationStat::kAttemptBytecodeCompilation);
136cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    if (compiled_intrinsics == 0u && compiled_native_stubs == 0u && bytecode_attempts == 0u) {
13748c2b03965830c73cdddeae8aea8030f08430137Calin Juravle      LOG(INFO) << "Did not compile any method.";
13848c2b03965830c73cdddeae8aea8030f08430137Calin Juravle    } else {
139cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      uint32_t compiled_bytecode_methods =
140cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko          GetStat(MethodCompilationStat::kCompiledBytecode);
141cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      // Successful intrinsic compilation preempts other compilation attempts but failed intrinsic
142cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      // compilation shall still count towards bytecode or native stub compilation attempts.
143cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      uint32_t num_compilation_attempts =
144cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko          compiled_intrinsics + compiled_native_stubs + bytecode_attempts;
145cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      uint32_t num_successful_compilations =
146cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko          compiled_intrinsics + compiled_native_stubs + compiled_bytecode_methods;
147cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      float compiled_percent = num_successful_compilations * 100.0f / num_compilation_attempts;
148cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      LOG(INFO) << "Attempted compilation of "
149cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko          << num_compilation_attempts << " methods: " << std::fixed << std::setprecision(2)
150cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko          << compiled_percent << "% (" << num_successful_compilations << ") compiled.";
151cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko
152cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      for (size_t i = 0; i < arraysize(compile_stats_); ++i) {
15348c2b03965830c73cdddeae8aea8030f08430137Calin Juravle        if (compile_stats_[i] != 0) {
154cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko          LOG(INFO) << "OptStat#" << static_cast<MethodCompilationStat>(i) << ": "
155da9badb9edea5e0d18cd9f97eff0d0937ad48310Andreas Gampe              << compile_stats_[i];
15648c2b03965830c73cdddeae8aea8030f08430137Calin Juravle        }
15748c2b03965830c73cdddeae8aea8030f08430137Calin Juravle      }
15848c2b03965830c73cdddeae8aea8030f08430137Calin Juravle    }
15948c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  }
16048c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
161438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko  void AddTo(OptimizingCompilerStats* other_stats) {
162cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    for (size_t i = 0; i != arraysize(compile_stats_); ++i) {
163438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko      uint32_t count = compile_stats_[i];
164438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko      if (count != 0) {
165438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko        other_stats->RecordStat(static_cast<MethodCompilationStat>(i), count);
166438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko      }
167438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko    }
168438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko  }
169438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko
170438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko  void Reset() {
171cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko    for (std::atomic<uint32_t>& stat : compile_stats_) {
172cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko      stat = 0u;
173438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko    }
174438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko  }
175438709f4f2454854f09a3b5c058834bbf772aaa8Vladimir Marko
17648c2b03965830c73cdddeae8aea8030f08430137Calin Juravle private:
177cd09e1f4f9902b82fa62cb2da984ea499e3b2d70Vladimir Marko  std::atomic<uint32_t> compile_stats_[static_cast<size_t>(MethodCompilationStat::kLastStat)];
17848c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
17948c2b03965830c73cdddeae8aea8030f08430137Calin Juravle  DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats);
18048c2b03965830c73cdddeae8aea8030f08430137Calin Juravle};
18148c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
1821e065a54845da12541572f4f149e6ab0dcd20180Igor Murashkininline void MaybeRecordStat(OptimizingCompilerStats* compiler_stats,
1831e065a54845da12541572f4f149e6ab0dcd20180Igor Murashkin                            MethodCompilationStat stat,
1841e065a54845da12541572f4f149e6ab0dcd20180Igor Murashkin                            uint32_t count = 1) {
1851e065a54845da12541572f4f149e6ab0dcd20180Igor Murashkin  if (compiler_stats != nullptr) {
1861e065a54845da12541572f4f149e6ab0dcd20180Igor Murashkin    compiler_stats->RecordStat(stat, count);
1871e065a54845da12541572f4f149e6ab0dcd20180Igor Murashkin  }
1881e065a54845da12541572f4f149e6ab0dcd20180Igor Murashkin}
1891e065a54845da12541572f4f149e6ab0dcd20180Igor Murashkin
19048c2b03965830c73cdddeae8aea8030f08430137Calin Juravle}  // namespace art
19148c2b03965830c73cdddeae8aea8030f08430137Calin Juravle
19248c2b03965830c73cdddeae8aea8030f08430137Calin Juravle#endif  // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_
193