Home | History | Annotate | Download | only in optimizing
      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 "base/atomic.h"
     26 #include "base/globals.h"
     27 #include "base/logging.h"  // For VLOG_IS_ON.
     28 
     29 namespace art {
     30 
     31 enum class MethodCompilationStat {
     32   kAttemptBytecodeCompilation = 0,
     33   kAttemptIntrinsicCompilation,
     34   kCompiledNativeStub,
     35   kCompiledIntrinsic,
     36   kCompiledBytecode,
     37   kCHAInline,
     38   kInlinedInvoke,
     39   kReplacedInvokeWithSimplePattern,
     40   kInstructionSimplifications,
     41   kInstructionSimplificationsArch,
     42   kUnresolvedMethod,
     43   kUnresolvedField,
     44   kUnresolvedFieldNotAFastAccess,
     45   kRemovedCheckedCast,
     46   kRemovedDeadInstruction,
     47   kRemovedNullCheck,
     48   kNotCompiledSkipped,
     49   kNotCompiledInvalidBytecode,
     50   kNotCompiledThrowCatchLoop,
     51   kNotCompiledAmbiguousArrayOp,
     52   kNotCompiledHugeMethod,
     53   kNotCompiledLargeMethodNoBranches,
     54   kNotCompiledMalformedOpcode,
     55   kNotCompiledNoCodegen,
     56   kNotCompiledPathological,
     57   kNotCompiledSpaceFilter,
     58   kNotCompiledUnhandledInstruction,
     59   kNotCompiledUnsupportedIsa,
     60   kNotCompiledVerificationError,
     61   kNotCompiledVerifyAtRuntime,
     62   kInlinedMonomorphicCall,
     63   kInlinedPolymorphicCall,
     64   kMonomorphicCall,
     65   kPolymorphicCall,
     66   kMegamorphicCall,
     67   kBooleanSimplified,
     68   kIntrinsicRecognized,
     69   kLoopInvariantMoved,
     70   kLoopVectorized,
     71   kLoopVectorizedIdiom,
     72   kSelectGenerated,
     73   kRemovedInstanceOf,
     74   kInlinedInvokeVirtualOrInterface,
     75   kImplicitNullCheckGenerated,
     76   kExplicitNullCheckGenerated,
     77   kSimplifyIf,
     78   kSimplifyThrowingInvoke,
     79   kInstructionSunk,
     80   kNotInlinedUnresolvedEntrypoint,
     81   kNotInlinedDexCache,
     82   kNotInlinedStackMaps,
     83   kNotInlinedEnvironmentBudget,
     84   kNotInlinedInstructionBudget,
     85   kNotInlinedLoopWithoutExit,
     86   kNotInlinedIrreducibleLoop,
     87   kNotInlinedAlwaysThrows,
     88   kNotInlinedInfiniteLoop,
     89   kNotInlinedTryCatch,
     90   kNotInlinedRegisterAllocator,
     91   kNotInlinedCannotBuild,
     92   kNotInlinedNotVerified,
     93   kNotInlinedCodeItem,
     94   kNotInlinedWont,
     95   kNotInlinedRecursiveBudget,
     96   kNotInlinedProxy,
     97   kConstructorFenceGeneratedNew,
     98   kConstructorFenceGeneratedFinal,
     99   kConstructorFenceRemovedLSE,
    100   kConstructorFenceRemovedPFRA,
    101   kConstructorFenceRemovedCFRE,
    102   kJitOutOfMemoryForCommit,
    103   kLastStat
    104 };
    105 std::ostream& operator<<(std::ostream& os, const MethodCompilationStat& rhs);
    106 
    107 class OptimizingCompilerStats {
    108  public:
    109   OptimizingCompilerStats() {
    110     // The std::atomic<> default constructor leaves values uninitialized, so initialize them now.
    111     Reset();
    112   }
    113 
    114   void RecordStat(MethodCompilationStat stat, uint32_t count = 1) {
    115     size_t stat_index = static_cast<size_t>(stat);
    116     DCHECK_LT(stat_index, arraysize(compile_stats_));
    117     compile_stats_[stat_index] += count;
    118   }
    119 
    120   uint32_t GetStat(MethodCompilationStat stat) const {
    121     size_t stat_index = static_cast<size_t>(stat);
    122     DCHECK_LT(stat_index, arraysize(compile_stats_));
    123     return compile_stats_[stat_index];
    124   }
    125 
    126   void Log() const {
    127     if (!kIsDebugBuild && !VLOG_IS_ON(compiler)) {
    128       // Log only in debug builds or if the compiler is verbose.
    129       return;
    130     }
    131 
    132     uint32_t compiled_intrinsics = GetStat(MethodCompilationStat::kCompiledIntrinsic);
    133     uint32_t compiled_native_stubs = GetStat(MethodCompilationStat::kCompiledNativeStub);
    134     uint32_t bytecode_attempts =
    135         GetStat(MethodCompilationStat::kAttemptBytecodeCompilation);
    136     if (compiled_intrinsics == 0u && compiled_native_stubs == 0u && bytecode_attempts == 0u) {
    137       LOG(INFO) << "Did not compile any method.";
    138     } else {
    139       uint32_t compiled_bytecode_methods =
    140           GetStat(MethodCompilationStat::kCompiledBytecode);
    141       // Successful intrinsic compilation preempts other compilation attempts but failed intrinsic
    142       // compilation shall still count towards bytecode or native stub compilation attempts.
    143       uint32_t num_compilation_attempts =
    144           compiled_intrinsics + compiled_native_stubs + bytecode_attempts;
    145       uint32_t num_successful_compilations =
    146           compiled_intrinsics + compiled_native_stubs + compiled_bytecode_methods;
    147       float compiled_percent = num_successful_compilations * 100.0f / num_compilation_attempts;
    148       LOG(INFO) << "Attempted compilation of "
    149           << num_compilation_attempts << " methods: " << std::fixed << std::setprecision(2)
    150           << compiled_percent << "% (" << num_successful_compilations << ") compiled.";
    151 
    152       for (size_t i = 0; i < arraysize(compile_stats_); ++i) {
    153         if (compile_stats_[i] != 0) {
    154           LOG(INFO) << "OptStat#" << static_cast<MethodCompilationStat>(i) << ": "
    155               << compile_stats_[i];
    156         }
    157       }
    158     }
    159   }
    160 
    161   void AddTo(OptimizingCompilerStats* other_stats) {
    162     for (size_t i = 0; i != arraysize(compile_stats_); ++i) {
    163       uint32_t count = compile_stats_[i];
    164       if (count != 0) {
    165         other_stats->RecordStat(static_cast<MethodCompilationStat>(i), count);
    166       }
    167     }
    168   }
    169 
    170   void Reset() {
    171     for (std::atomic<uint32_t>& stat : compile_stats_) {
    172       stat = 0u;
    173     }
    174   }
    175 
    176  private:
    177   std::atomic<uint32_t> compile_stats_[static_cast<size_t>(MethodCompilationStat::kLastStat)];
    178 
    179   DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats);
    180 };
    181 
    182 inline void MaybeRecordStat(OptimizingCompilerStats* compiler_stats,
    183                             MethodCompilationStat stat,
    184                             uint32_t count = 1) {
    185   if (compiler_stats != nullptr) {
    186     compiler_stats->RecordStat(stat, count);
    187   }
    188 }
    189 
    190 }  // namespace art
    191 
    192 #endif  // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_
    193