summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdexfile/dex/class_accessor-inl.h59
-rw-r--r--libdexfile/dex/class_accessor.h24
-rw-r--r--libdexfile/dex/class_iterator.h101
-rw-r--r--libdexfile/dex/code_item_accessors.h5
-rw-r--r--libdexfile/dex/dex_file-inl.h5
-rw-r--r--libdexfile/dex/dex_file.h3
-rw-r--r--tools/dexanalyze/dexanalyze_experiments.cc21
7 files changed, 176 insertions, 42 deletions
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index bcd0a7b66c..5cfbcaa359 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -20,19 +20,22 @@
#include "class_accessor.h"
#include "base/leb128.h"
+#include "class_iterator.h"
+#include "code_item_accessors-inl.h"
namespace art {
-inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def)
- : ClassAccessor(dex_file, dex_file.GetClassData(class_def)) {}
+inline ClassAccessor::ClassAccessor(const ClassIteratorData& data)
+ : ClassAccessor(data.dex_file_, data.dex_file_.GetClassDef(data.class_def_idx_)) {}
-inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const uint8_t* class_data)
+inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def)
: dex_file_(dex_file),
- ptr_pos_(class_data),
- num_static_fields_(class_data != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
- num_instance_fields_(class_data != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
- num_direct_methods_(class_data != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
- num_virtual_methods_(class_data != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {}
+ descriptor_index_(class_def.class_idx_),
+ ptr_pos_(dex_file.GetClassData(class_def)),
+ num_static_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
+ num_instance_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
+ num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
+ num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {}
inline const uint8_t* ClassAccessor::Method::Read(const uint8_t* ptr) {
method_idx_ += DecodeUnsignedLeb128(&ptr);
@@ -57,25 +60,33 @@ inline void ClassAccessor::VisitMethodsAndFields(
const DirectMethodVisitor& direct_method_visitor,
const VirtualMethodVisitor& virtual_method_visitor) const {
const uint8_t* ptr = ptr_pos_;
- for (size_t i = 0; i < num_static_fields_; ++i) {
+ {
Field data;
- ptr = data.Read(ptr);
- static_field_visitor(data);
+ for (size_t i = 0; i < num_static_fields_; ++i) {
+ ptr = data.Read(ptr);
+ static_field_visitor(data);
+ }
}
- for (size_t i = 0; i < num_instance_fields_; ++i) {
+ {
Field data;
- ptr = data.Read(ptr);
- instance_field_visitor(data);
+ for (size_t i = 0; i < num_instance_fields_; ++i) {
+ ptr = data.Read(ptr);
+ instance_field_visitor(data);
+ }
}
- for (size_t i = 0; i < num_direct_methods_; ++i) {
- Method data;
- ptr = data.Read(ptr);
- direct_method_visitor(data);
+ {
+ Method data(dex_file_);
+ for (size_t i = 0; i < num_direct_methods_; ++i) {
+ ptr = data.Read(ptr);
+ direct_method_visitor(data);
+ }
}
- for (size_t i = 0; i < num_virtual_methods_; ++i) {
- Method data;
- ptr = data.Read(ptr);
- virtual_method_visitor(data);
+ {
+ Method data(dex_file_);
+ for (size_t i = 0; i < num_virtual_methods_; ++i) {
+ ptr = data.Read(ptr);
+ virtual_method_visitor(data);
+ }
}
}
@@ -99,6 +110,10 @@ inline const DexFile::CodeItem* ClassAccessor::GetCodeItem(const Method& method)
return dex_file_.GetCodeItem(method.GetCodeItemOffset());
}
+inline CodeItemInstructionAccessor ClassAccessor::Method::GetInstructions() const {
+ return CodeItemInstructionAccessor(dex_file_, dex_file_.GetCodeItem(GetCodeItemOffset()));
+}
+
} // namespace art
#endif // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index 59a6b5dfa5..835c4e2eb7 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -18,10 +18,13 @@
#define ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_
#include "base/utils.h"
+#include "code_item_accessors.h"
#include "dex_file.h"
namespace art {
+class ClassIteratorData;
+
// Classes to access Dex data.
class ClassAccessor {
public:
@@ -40,10 +43,15 @@ class ClassAccessor {
return code_off_;
}
+ CodeItemInstructionAccessor GetInstructions() const;
+
private:
+ explicit Method(const DexFile& dex_file) : dex_file_(dex_file) {}
+
const uint8_t* Read(const uint8_t* ptr);
// A decoded version of the method of a class_data_item.
+ const DexFile& dex_file_;
uint32_t method_idx_ = 0u;
uint32_t access_flags_ = 0u;
uint32_t code_off_ = 0u;
@@ -72,7 +80,10 @@ class ClassAccessor {
friend class ClassAccessor;
};
- ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def);
+ // Not explicit specifically for range-based loops.
+ ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data);
+
+ ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def);
// Return the code item for a method.
const DexFile::CodeItem* GetCodeItem(const Method& method) const;
@@ -112,18 +123,19 @@ class ClassAccessor {
return num_virtual_methods_;
}
- protected:
- ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, const uint8_t* class_data);
+ // TODO: Deprecate
+ dex::TypeIndex GetDescriptorIndex() const {
+ return descriptor_index_;
+ }
+ protected:
const DexFile& dex_file_;
+ const dex::TypeIndex descriptor_index_ = {};
const uint8_t* ptr_pos_ = nullptr; // Pointer into stream of class_data_item.
const uint32_t num_static_fields_ = 0u;
const uint32_t num_instance_fields_ = 0u;
const uint32_t num_direct_methods_ = 0u;
const uint32_t num_virtual_methods_ = 0u;
- // Only cache descriptor.
- const void* class_def_ = nullptr;
- const void* class_data_ = nullptr;
};
} // namespace art
diff --git a/libdexfile/dex/class_iterator.h b/libdexfile/dex/class_iterator.h
new file mode 100644
index 0000000000..477c93b508
--- /dev/null
+++ b/libdexfile/dex/class_iterator.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_LIBDEXFILE_DEX_CLASS_ITERATOR_H_
+#define ART_LIBDEXFILE_DEX_CLASS_ITERATOR_H_
+
+#include "base/logging.h"
+
+namespace art {
+
+class ClassAccessor;
+class ClassIterator;
+class DexFile;
+
+// Holder class, used to construct ClassAccessors.
+class ClassIteratorData {
+ public:
+ ClassIteratorData(const DexFile& dex_file, uint32_t class_def_idx)
+ : dex_file_(dex_file),
+ class_def_idx_(class_def_idx) {}
+
+ private:
+ const DexFile& dex_file_;
+ uint32_t class_def_idx_ = 0u;
+
+ friend class ClassAccessor;
+ friend class ClassIterator;
+};
+
+// Iterator for visiting classes in a Dex file.
+class ClassIterator : public std::iterator<std::forward_iterator_tag, ClassIteratorData> {
+ public:
+ using value_type = std::iterator<std::forward_iterator_tag, ClassIteratorData>::value_type;
+ using difference_type = std::iterator<std::forward_iterator_tag, value_type>::difference_type;
+
+ ClassIterator(const DexFile& dex_file, uint32_t class_def_idx)
+ : data_(dex_file, class_def_idx) {}
+
+ // Value after modification.
+ ClassIterator& operator++() {
+ ++data_.class_def_idx_;
+ return *this;
+ }
+
+ // Value before modification.
+ ClassIterator operator++(int) {
+ ClassIterator temp = *this;
+ ++*this;
+ return temp;
+ }
+
+ const value_type& operator*() const {
+ return data_;
+ }
+
+ bool operator==(const ClassIterator& rhs) const {
+ DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
+ return data_.class_def_idx_ == rhs.data_.class_def_idx_;
+ }
+
+ bool operator!=(const ClassIterator& rhs) const {
+ return !(*this == rhs);
+ }
+
+ bool operator<(const ClassIterator& rhs) const {
+ DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
+ return data_.class_def_idx_ < rhs.data_.class_def_idx_;
+ }
+
+ bool operator>(const ClassIterator& rhs) const {
+ return rhs < *this;
+ }
+
+ bool operator<=(const ClassIterator& rhs) const {
+ return !(rhs < *this);
+ }
+
+ bool operator>=(const ClassIterator& rhs) const {
+ return !(*this < rhs);
+ }
+
+ protected:
+ ClassIteratorData data_;
+};
+
+} // namespace art
+
+#endif // ART_LIBDEXFILE_DEX_CLASS_ITERATOR_H_
diff --git a/libdexfile/dex/code_item_accessors.h b/libdexfile/dex/code_item_accessors.h
index ba7c126ed8..5786d3f611 100644
--- a/libdexfile/dex/code_item_accessors.h
+++ b/libdexfile/dex/code_item_accessors.h
@@ -47,6 +47,11 @@ class CodeItemInstructionAccessor {
return insns_size_in_code_units_;
}
+ uint32_t InsnsSizeInBytes() const {
+ static constexpr uint32_t kCodeUnitSizeInBytes = 2u;
+ return insns_size_in_code_units_ * kCodeUnitSizeInBytes;
+ }
+
const uint16_t* Insns() const {
return insns_;
}
diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h
index e78e8d7a44..f5dd374253 100644
--- a/libdexfile/dex/dex_file-inl.h
+++ b/libdexfile/dex/dex_file-inl.h
@@ -20,6 +20,7 @@
#include "base/casts.h"
#include "base/leb128.h"
#include "base/stringpiece.h"
+#include "class_iterator.h"
#include "compact_dex_file.h"
#include "dex_file.h"
#include "invoke_type.h"
@@ -527,6 +528,10 @@ inline void DexFile::ClassDef::VisitMethods(const DexFile* dex_file, const Visit
}
}
+inline IterationRange<ClassIterator> DexFile::GetClasses() const {
+ return { ClassIterator(*this, 0u), ClassIterator(*this, NumClassDefs()) };
+}
+
} // namespace art
#endif // ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index 87d2c48ff1..f1f8b505bd 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -27,6 +27,7 @@
#include "base/iteration_range.h"
#include "base/macros.h"
#include "base/value_object.h"
+#include "class_iterator.h"
#include "dex_file_types.h"
#include "dex_instruction_iterator.h"
#include "hidden_api_access_flags.h"
@@ -1012,6 +1013,8 @@ class DexFile {
// Changes the dex file pointed to by class_it to not have any hiddenapi flags.
static void UnHideAccessFlags(ClassDataItemIterator& class_it);
+ inline IterationRange<ClassIterator> GetClasses() const;
+
protected:
// First Dex format version supporting default methods.
static const uint32_t kDefaultMethodsVersion = 37;
diff --git a/tools/dexanalyze/dexanalyze_experiments.cc b/tools/dexanalyze/dexanalyze_experiments.cc
index f9bf45da4f..427a465caf 100644
--- a/tools/dexanalyze/dexanalyze_experiments.cc
+++ b/tools/dexanalyze/dexanalyze_experiments.cc
@@ -24,6 +24,7 @@
#include "android-base/stringprintf.h"
#include "dex/class_accessor-inl.h"
+#include "dex/class_iterator.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_instruction-inl.h"
#include "dex/standard_dex_file.h"
@@ -125,20 +126,12 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) {
num_field_ids_ += dex_file.NumFieldIds();
num_type_ids_ += dex_file.NumTypeIds();
num_class_defs_ += dex_file.NumClassDefs();
- for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); ++class_def_index) {
- const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- ClassAccessor accessor(dex_file, class_def);
+ for (ClassAccessor accessor : dex_file.GetClasses()) {
std::set<size_t> unique_method_ids;
std::set<size_t> unique_string_ids;
accessor.VisitMethods([&](const ClassAccessor::Method& method) {
- const DexFile::CodeItem* code_item = accessor.GetCodeItem(method);
- if (code_item == nullptr) {
- return;
- }
- CodeItemInstructionAccessor instructions(dex_file, code_item);
- const uint16_t* code_ptr = instructions.Insns();
- dex_code_bytes_ += instructions.InsnsSizeInCodeUnits() * sizeof(code_ptr[0]);
- for (const DexInstructionPcPair& inst : instructions) {
+ dex_code_bytes_ += method.GetInstructions().InsnsSizeInBytes();
+ for (const DexInstructionPcPair& inst : method.GetInstructions()) {
switch (inst->Opcode()) {
case Instruction::CONST_STRING: {
const dex::StringIndex string_index(inst->VRegB_21c());
@@ -157,7 +150,7 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) {
case Instruction::INVOKE_VIRTUAL_RANGE: {
bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE);
uint32_t method_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
- if (dex_file.GetMethodId(method_idx).class_idx_ == class_def.class_idx_) {
+ if (dex_file.GetMethodId(method_idx).class_idx_ == accessor.GetDescriptorIndex()) {
++same_class_virtual_;
} else {
++other_class_virtual_;
@@ -169,7 +162,7 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) {
case Instruction::INVOKE_DIRECT_RANGE: {
bool is_range = (inst->Opcode() == Instruction::INVOKE_DIRECT_RANGE);
uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
- if (dex_file.GetMethodId(method_idx).class_idx_ == class_def.class_idx_) {
+ if (dex_file.GetMethodId(method_idx).class_idx_ == accessor.GetDescriptorIndex()) {
++same_class_direct_;
} else {
++other_class_direct_;
@@ -181,7 +174,7 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) {
case Instruction::INVOKE_STATIC_RANGE: {
bool is_range = (inst->Opcode() == Instruction::INVOKE_STATIC_RANGE);
uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
- if (dex_file.GetMethodId(method_idx).class_idx_ == class_def.class_idx_) {
+ if (dex_file.GetMethodId(method_idx).class_idx_ == accessor.GetDescriptorIndex()) {
++same_class_static_;
} else {
++other_class_static_;