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