dexanalyze: distinguish fields from other classes.
Test: Manulally run dexanalyze.
Change-Id: I2428be2cf0a5e738307fb792f1a932bb0e9a3d9e
diff --git a/tools/dexanalyze/dexanalyze_experiments.cc b/tools/dexanalyze/dexanalyze_experiments.cc
index e216f89..c5f7e8e 100644
--- a/tools/dexanalyze/dexanalyze_experiments.cc
+++ b/tools/dexanalyze/dexanalyze_experiments.cc
@@ -332,6 +332,26 @@
for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
instance_field_index_map_[field.GetIndex()] = current_idx++;
}
+ auto ProcessFieldIndex = [&](uint32_t dex_field_idx,
+ uint32_t inout,
+ const std::map<uint32_t, uint32_t>& index_map,
+ /*inout*/ FieldAccessStats* stats) {
+ auto it = index_map.find(dex_field_idx);
+ if (it != index_map.end()) {
+ if (it->second < FieldAccessStats::kMaxFieldIndex) {
+ ++stats->field_index_[it->second];
+ } else {
+ ++stats->field_index_other_;
+ }
+ } else {
+ ++stats->field_index_other_class_;
+ }
+ if (it != index_map.end() &&
+ it->second < FieldAccessStats::kShortBytecodeFieldIndexOutCutOff &&
+ inout < FieldAccessStats::kShortBytecodeInOutCutOff) {
+ ++stats->short_bytecode_;
+ }
+ };
auto ProcessInstanceField = [&](const Instruction& inst,
uint32_t first_arg_reg,
const std::map<uint32_t, uint32_t>& index_map,
@@ -344,17 +364,7 @@
// FIXME: This is weird if receiver < first_arg_reg.
++stats->receiver_[(receiver - first_arg_reg) & 0xF];
if (first_arg_reg == receiver) {
- auto it = index_map.find(dex_field_idx);
- if (it != index_map.end() && it->second < FieldAccessStats::kMaxFieldIndex) {
- ++stats->field_index_[it->second];
- } else {
- ++stats->field_index_other_;
- }
- if (it != index_map.end() &&
- it->second < FieldAccessStats::kShortBytecodeFieldIndexOutCutOff &&
- input < FieldAccessStats::kShortBytecodeInOutCutOff) {
- ++stats->short_bytecode_;
- }
+ ProcessFieldIndex(dex_field_idx, input, index_map, stats);
}
};
auto ProcessStaticField = [&](const Instruction& inst,
@@ -368,17 +378,7 @@
} else {
++stats->inout_other_;
}
- auto it = index_map.find(dex_field_idx);
- if (it != index_map.end() && it->second < FieldAccessStats::kMaxFieldIndex) {
- ++stats->field_index_[it->second];
- } else {
- ++stats->field_index_other_;
- }
- if (it != index_map.end() &&
- it->second < FieldAccessStats::kShortBytecodeFieldIndexOutCutOff &&
- output < FieldAccessStats::kShortBytecodeInOutCutOff) {
- ++stats->short_bytecode_;
- }
+ ProcessFieldIndex(dex_field_idx, output, index_map, stats);
};
for (const ClassAccessor::Method& method : accessor.GetMethods()) {
@@ -549,6 +549,18 @@
}
void CountDexIndices::Dump(std::ostream& os, uint64_t total_size) const {
+ auto DumpFieldIndexes = [&](const FieldAccessStats& stats) {
+ const uint64_t fields_idx_total = std::accumulate(
+ stats.field_index_,
+ stats.field_index_ + FieldAccessStats::kMaxFieldIndex,
+ stats.field_index_other_ + stats.field_index_other_class_);
+ for (size_t i = 0; i < FieldAccessStats::kMaxFieldIndex; ++i) {
+ os << " field_idx=" << i << ": " << Percent(stats.field_index_[i], fields_idx_total) << "\n";
+ }
+ os << " field_idx=other: " << Percent(stats.field_index_other_, fields_idx_total) << "\n";
+ os << " field_idx=other_class: " << Percent(stats.field_index_other_class_, fields_idx_total)
+ << "\n";
+ };
auto DumpInstanceFieldStats = [&](const char* tag, const InstanceFieldAccessStats& stats) {
const uint64_t fields_total = std::accumulate(stats.inout_, stats.inout_ + 16u, 0u);
os << tag << "\n";
@@ -560,14 +572,7 @@
for (size_t i = 0; i < 16; ++i) {
os << " " << inout_tag << "=" << i << ": " << Percent(stats.inout_[i], fields_total) << "\n";
}
- const uint64_t fields_idx_total = std::accumulate(
- stats.field_index_,
- stats.field_index_ + FieldAccessStats::kMaxFieldIndex,
- stats.field_index_other_);
- for (size_t i = 0; i < FieldAccessStats::kMaxFieldIndex; ++i) {
- os << " field_idx=" << i << ": " << Percent(stats.field_index_[i], fields_idx_total) << "\n";
- }
- os << " field_idx=other: " << Percent(stats.field_index_other_, fields_idx_total) << "\n";
+ DumpFieldIndexes(stats);
os << " short_bytecode: " << Percent(stats.short_bytecode_, fields_total) << "\n";
os << " short_bytecode_savings=" << Percent(stats.short_bytecode_ * 2, total_size) << "\n";
};
@@ -584,14 +589,7 @@
os << " " << inout_tag << "=" << i << ": " << Percent(stats.inout_[i], fields_total) << "\n";
}
os << " " << inout_tag << "=other: " << Percent(stats.inout_other_, fields_total) << "\n";
- const uint64_t fields_idx_total = std::accumulate(
- stats.field_index_,
- stats.field_index_ + FieldAccessStats::kMaxFieldIndex,
- stats.field_index_other_);
- for (size_t i = 0; i < FieldAccessStats::kMaxFieldIndex; ++i) {
- os << " field_idx=" << i << ": " << Percent(stats.field_index_[i], fields_idx_total) << "\n";
- }
- os << " field_idx=other: " << Percent(stats.field_index_other_, fields_idx_total) << "\n";
+ DumpFieldIndexes(stats);
os << " short_bytecode: " << Percent(stats.short_bytecode_, fields_total) << "\n";
os << " short_bytecode_savings=" << Percent(stats.short_bytecode_ * 2, total_size) << "\n";
};
diff --git a/tools/dexanalyze/dexanalyze_experiments.h b/tools/dexanalyze/dexanalyze_experiments.h
index c59cd0b..0e147dd 100644
--- a/tools/dexanalyze/dexanalyze_experiments.h
+++ b/tools/dexanalyze/dexanalyze_experiments.h
@@ -102,10 +102,14 @@
static constexpr size_t kMaxFieldIndex = 32;
uint64_t field_index_[kMaxFieldIndex] = {};
uint64_t field_index_other_ = 0u;
- uint64_t inout_[16] = {}; // Input for IPUT/SPUT, output for IGET/SGET.
+ uint64_t field_index_other_class_ = 0u; // Includes superclass fields referenced with
+ // type index pointing to this class.
+
static constexpr size_t kShortBytecodeFieldIndexOutCutOff = 16u;
static constexpr size_t kShortBytecodeInOutCutOff = 16u;
uint64_t short_bytecode_ = 0u;
+
+ uint64_t inout_[16] = {}; // Input for IPUT/SPUT, output for IGET/SGET.
};
struct InstanceFieldAccessStats : FieldAccessStats {
uint64_t receiver_[16] = {};