Home | History | Annotate | Download | only in dexanalyze
      1 /*
      2  * Copyright (C) 2018 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_TOOLS_DEXANALYZE_DEXANALYZE_EXPERIMENTS_H_
     18 #define ART_TOOLS_DEXANALYZE_DEXANALYZE_EXPERIMENTS_H_
     19 
     20 #include <cstdint>
     21 #include <iosfwd>
     22 #include <memory>
     23 #include <set>
     24 #include <unordered_map>
     25 #include <vector>
     26 
     27 #include "base/macros.h"
     28 #include "dex/dex_instruction.h"
     29 
     30 namespace art {
     31 
     32 class DexFile;
     33 
     34 namespace dexanalyze {
     35 
     36 enum class VerboseLevel : size_t {
     37   kQuiet,
     38   kNormal,
     39   kEverything,
     40 };
     41 
     42 bool IsRange(Instruction::Code code);
     43 
     44 uint16_t NumberOfArgs(const Instruction& inst);
     45 
     46 uint16_t DexMethodIndex(const Instruction& inst);
     47 
     48 std::string PercentDivide(uint64_t value, uint64_t max);
     49 
     50 size_t PrefixLen(const std::string& a, const std::string& b);
     51 
     52 std::string Percent(uint64_t value, uint64_t max);
     53 
     54 // An experiment a stateful visitor that runs on dex files. Results are cumulative.
     55 class Experiment {
     56  public:
     57   virtual ~Experiment() {}
     58   virtual void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
     59   virtual void ProcessDexFile(const DexFile&) {}
     60   virtual void Dump(std::ostream& os, uint64_t total_size) const = 0;
     61 
     62   VerboseLevel verbose_level_ = VerboseLevel::kNormal;
     63 };
     64 
     65 // Analyze debug info sizes.
     66 class AnalyzeDebugInfo  : public Experiment {
     67  public:
     68   void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) override;
     69   void Dump(std::ostream& os, uint64_t total_size) const override;
     70 
     71  private:
     72   int64_t total_bytes_ = 0u;
     73   int64_t total_entropy_ = 0u;
     74   int64_t total_opcode_bytes_ = 0u;
     75   int64_t total_opcode_entropy_ = 0u;
     76   int64_t total_non_header_bytes_ = 0u;
     77   int64_t total_unique_non_header_bytes_ = 0u;
     78   // Opcode and related data.
     79   int64_t total_end_seq_bytes_ = 0u;
     80   int64_t total_advance_pc_bytes_ = 0u;
     81   int64_t total_advance_line_bytes_ = 0u;
     82   int64_t total_start_local_bytes_ = 0u;
     83   int64_t total_start_local_extended_bytes_ = 0u;
     84   int64_t total_end_local_bytes_ = 0u;
     85   int64_t total_restart_local_bytes_ = 0u;
     86   int64_t total_epilogue_bytes_ = 0u;
     87   int64_t total_set_file_bytes_ = 0u;
     88   int64_t total_other_bytes_ = 0u;
     89 };
     90 
     91 // Count numbers of dex indices.
     92 class CountDexIndices : public Experiment {
     93  public:
     94   void ProcessDexFile(const DexFile& dex_file) override;
     95   void ProcessDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files) override;
     96 
     97   void Dump(std::ostream& os, uint64_t total_size) const override;
     98 
     99  private:
    100   // Total string ids loaded from dex code.
    101   size_t num_string_ids_from_code_ = 0;
    102   size_t total_unique_method_ids_ = 0;
    103   size_t total_unique_string_ids_ = 0;
    104   uint64_t total_unique_code_items_ = 0u;
    105 
    106   struct FieldAccessStats {
    107     static constexpr size_t kMaxFieldIndex = 32;
    108     uint64_t field_index_[kMaxFieldIndex] = {};
    109     uint64_t field_index_other_ = 0u;
    110     uint64_t field_index_other_class_ = 0u;  // Includes superclass fields referenced with
    111                                              // type index pointing to this class.
    112 
    113     static constexpr size_t kShortBytecodeFieldIndexOutCutOff = 16u;
    114     static constexpr size_t kShortBytecodeInOutCutOff = 16u;
    115     uint64_t short_bytecode_ = 0u;
    116 
    117     uint64_t inout_[16] = {};  // Input for IPUT/SPUT, output for IGET/SGET.
    118   };
    119   struct InstanceFieldAccessStats : FieldAccessStats {
    120     uint64_t receiver_[16] = {};
    121   };
    122   struct StaticFieldAccessStats : FieldAccessStats {
    123     uint64_t inout_other_ = 0u;  // Input for SPUT, output for SGET.
    124   };
    125   InstanceFieldAccessStats iget_stats_;
    126   InstanceFieldAccessStats iput_stats_;
    127   StaticFieldAccessStats sget_stats_;
    128   StaticFieldAccessStats sput_stats_;
    129 
    130   // Unique names.
    131   uint64_t total_unique_method_names_ = 0u;
    132   uint64_t total_unique_field_names_ = 0u;
    133   uint64_t total_unique_type_names_ = 0u;
    134   uint64_t total_unique_mf_names_ = 0u;
    135 
    136   // Other dex ids.
    137   size_t dex_code_bytes_ = 0;
    138   size_t num_string_ids_ = 0;
    139   size_t num_method_ids_ = 0;
    140   size_t num_field_ids_ = 0;
    141   size_t num_type_ids_ = 0;
    142   size_t num_class_defs_ = 0;
    143 
    144   // Invokes
    145   size_t same_class_direct_ = 0;
    146   size_t total_direct_ = 0;
    147   size_t same_class_virtual_ = 0;
    148   size_t total_virtual_ = 0;
    149   size_t same_class_static_ = 0;
    150   size_t total_static_ = 0;
    151   size_t same_class_interface_ = 0;
    152   size_t total_interface_ = 0;
    153   size_t same_class_super_ = 0;
    154   size_t total_super_ = 0;
    155 
    156   // Type usage.
    157   uint64_t uses_top_types_ = 0u;
    158   uint64_t uses_all_types_ = 0u;
    159   uint64_t total_unique_types_ = 0u;
    160 };
    161 
    162 // Measure various code metrics including args per invoke-virtual, fill/spill move patterns.
    163 class CodeMetrics : public Experiment {
    164  public:
    165   void ProcessDexFile(const DexFile& dex_file) override;
    166 
    167   void Dump(std::ostream& os, uint64_t total_size) const override;
    168 
    169  private:
    170   static constexpr size_t kMaxArgCount = 6;
    171   uint64_t arg_counts_[kMaxArgCount] = {};
    172   uint64_t move_result_savings_ = 0u;
    173 };
    174 
    175 }  // namespace dexanalyze
    176 }  // namespace art
    177 
    178 #endif  // ART_TOOLS_DEXANALYZE_DEXANALYZE_EXPERIMENTS_H_
    179