summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdexfile/dex/class_accessor-inl.h101
-rw-r--r--libdexfile/dex/class_accessor.h78
-rw-r--r--libdexfile/dex/class_accessor_test.cc10
-rw-r--r--libdexfile/dex/dex_file.cc17
-rw-r--r--libdexfile/dex/dex_file.h4
-rw-r--r--openjdkjvmti/fixed_up_dex_file.cc15
-rw-r--r--runtime/art_method.cc23
-rw-r--r--runtime/class_linker.cc290
-rw-r--r--runtime/class_linker.h13
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc29
-rw-r--r--runtime/vdex_file.cc40
-rw-r--r--runtime/verifier/method_verifier.cc164
-rw-r--r--runtime/verifier/method_verifier.h17
13 files changed, 417 insertions, 384 deletions
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index 3bb9e93e5a..49ca98d47f 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -37,26 +37,30 @@ inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const DexFile::Clas
num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {}
-inline void ClassAccessor::Method::Read() {
- index_ += DecodeUnsignedLeb128(&ptr_pos_);
- access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
- code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
+inline const uint8_t* ClassAccessor::Method::Read(const uint8_t* ptr) {
+ index_ += DecodeUnsignedLeb128(&ptr);
+ access_flags_ = DecodeUnsignedLeb128(&ptr);
+ code_off_ = DecodeUnsignedLeb128(&ptr);
+ return ptr;
}
-inline void ClassAccessor::Field::Read() {
- index_ += DecodeUnsignedLeb128(&ptr_pos_);
- access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+inline const uint8_t* ClassAccessor::Field::Read(const uint8_t* ptr) {
+ index_ += DecodeUnsignedLeb128(&ptr);
+ access_flags_ = DecodeUnsignedLeb128(&ptr);
+ return ptr;
}
template <typename DataType, typename Visitor>
-inline void ClassAccessor::VisitMembers(size_t count,
- const Visitor& visitor,
- DataType* data) const {
+inline const uint8_t* ClassAccessor::VisitMembers(size_t count,
+ const Visitor& visitor,
+ const uint8_t* ptr,
+ DataType* data) const {
DCHECK(data != nullptr);
for ( ; count != 0; --count) {
- data->Read();
+ ptr = data->Read(ptr);
visitor(*data);
}
+ return ptr;
}
template <typename StaticFieldVisitor,
@@ -68,15 +72,15 @@ inline void ClassAccessor::VisitFieldsAndMethods(
const InstanceFieldVisitor& instance_field_visitor,
const DirectMethodVisitor& direct_method_visitor,
const VirtualMethodVisitor& virtual_method_visitor) const {
- Field field(dex_file_, ptr_pos_);
- VisitMembers(num_static_fields_, static_field_visitor, &field);
+ Field field(dex_file_);
+ const uint8_t* ptr = VisitMembers(num_static_fields_, static_field_visitor, ptr_pos_, &field);
field.NextSection();
- VisitMembers(num_instance_fields_, instance_field_visitor, &field);
+ ptr = VisitMembers(num_instance_fields_, instance_field_visitor, ptr, &field);
- Method method(dex_file_, field.ptr_pos_, /*is_static_or_direct*/ true);
- VisitMembers(num_direct_methods_, direct_method_visitor, &method);
+ Method method(dex_file_, /*is_static_or_direct*/ true);
+ ptr = VisitMembers(num_direct_methods_, direct_method_visitor, ptr, &method);
method.NextSection();
- VisitMembers(num_virtual_methods_, virtual_method_visitor, &method);
+ ptr = VisitMembers(num_virtual_methods_, virtual_method_visitor, ptr, &method);
}
template <typename DirectMethodVisitor,
@@ -115,64 +119,23 @@ inline const DexFile::CodeItem* ClassAccessor::Method::GetCodeItem() const {
return dex_file_.GetCodeItem(code_off_);
}
-inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
- ClassAccessor::GetFieldsInternal(size_t count) const {
- return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, count, ptr_pos_),
- DataIterator<Field>(dex_file_, count, num_static_fields_, count, ptr_pos_) };
-}
-
-// Return an iteration range for the first <count> methods.
-inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
- ClassAccessor::GetMethodsInternal(size_t count) const {
- // Skip over the fields.
- Field field(dex_file_, ptr_pos_);
- VisitMembers(NumFields(), VoidFunctor(), &field);
- // Return the iterator pair.
- return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, count, field.ptr_pos_),
- DataIterator<Method>(dex_file_, count, num_direct_methods_, count, field.ptr_pos_) };
-}
-
inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields()
const {
- return GetFieldsInternal(num_static_fields_ + num_instance_fields_);
-}
-
-inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
- ClassAccessor::GetStaticFields() const {
- return GetFieldsInternal(num_static_fields_);
-}
-
-
-inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
- ClassAccessor::GetInstanceFields() const {
- IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> fields = GetFields();
- // Skip the static fields.
- return { std::next(fields.begin(), NumStaticFields()), fields.end() };
+ const uint32_t limit = num_static_fields_ + num_instance_fields_;
+ return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, limit, ptr_pos_),
+ DataIterator<Field>(dex_file_, limit, num_static_fields_, limit, ptr_pos_) };
}
inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
ClassAccessor::GetMethods() const {
- return GetMethodsInternal(NumMethods());
-}
-
-inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
- ClassAccessor::GetDirectMethods() const {
- return GetMethodsInternal(NumDirectMethods());
-}
-
-inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
- ClassAccessor::GetVirtualMethods() const {
- IterationRange<DataIterator<Method>> methods = GetMethods();
- // Skip the direct fields.
- return { std::next(methods.begin(), NumDirectMethods()), methods.end() };
-}
-
-inline void ClassAccessor::Field::UnHideAccessFlags() const {
- DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ false);
-}
-
-inline void ClassAccessor::Method::UnHideAccessFlags() const {
- DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ true);
+ // Skip over the fields.
+ Field field(dex_file_);
+ const size_t skip_count = num_static_fields_ + num_instance_fields_;
+ const uint8_t* ptr_pos = VisitMembers(skip_count, VoidFunctor(), ptr_pos_, &field);
+ // Return the iterator pair for all the methods.
+ const uint32_t limit = num_direct_methods_ + num_virtual_methods_;
+ return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, limit, ptr_pos),
+ DataIterator<Method>(dex_file_, limit, num_direct_methods_, limit, ptr_pos) };
}
} // namespace art
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index 4f0fd32e31..dda6e1c1a6 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -20,7 +20,6 @@
#include "base/utils.h"
#include "code_item_accessors.h"
#include "dex_file.h"
-#include "hidden_api_access_flags.h"
#include "invoke_type.h"
#include "method_reference.h"
#include "modifiers.h"
@@ -34,18 +33,12 @@ class ClassAccessor {
private:
class BaseItem {
public:
- explicit BaseItem(const uint8_t* ptr_pos) : ptr_pos_(ptr_pos) {}
-
uint32_t GetIndex() const {
return index_;
}
uint32_t GetAccessFlags() const {
- return HiddenApiAccessFlags::RemoveFromDex(access_flags_);
- }
-
- HiddenApiAccessFlags::ApiList DecodeHiddenAccessFlags() const {
- return HiddenApiAccessFlags::DecodeFromDex(access_flags_);
+ return access_flags_;
}
bool IsFinal() const {
@@ -53,8 +46,6 @@ class ClassAccessor {
}
protected:
- // Internal data pointer for reading.
- const uint8_t* ptr_pos_ = nullptr;
uint32_t index_ = 0u;
uint32_t access_flags_ = 0u;
};
@@ -85,18 +76,13 @@ class ClassAccessor {
return is_static_or_direct_;
}
- // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
- void UnHideAccessFlags() const;
-
private:
explicit Method(const DexFile& dex_file,
- const uint8_t* ptr_pos,
bool is_static_or_direct = true)
- : BaseItem(ptr_pos),
- dex_file_(dex_file),
+ : dex_file_(dex_file),
is_static_or_direct_(is_static_or_direct) {}
- void Read();
+ const uint8_t* Read(const uint8_t* ptr);
InvokeType GetDirectMethodInvokeType() const {
return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
@@ -113,7 +99,6 @@ class ClassAccessor {
}
}
- // Move to virtual method section.
void NextSection() {
DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
is_static_or_direct_ = false;
@@ -130,31 +115,20 @@ class ClassAccessor {
// A decoded version of the field of a class_data_item.
class Field : public BaseItem {
public:
- explicit Field(const DexFile& dex_file,
- const uint8_t* ptr_pos) : BaseItem(ptr_pos), dex_file_(dex_file) {}
+ explicit Field(const DexFile& dex_file) : dex_file_(dex_file) {}
const DexFile& GetDexFile() const {
return dex_file_;
}
- bool IsStatic() const {
- return is_static_;
- }
-
- // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
- void UnHideAccessFlags() const;
-
private:
- void Read();
+ const uint8_t* Read(const uint8_t* ptr);
- // Move to instance fields section.
void NextSection() {
index_ = 0u;
- is_static_ = false;
}
const DexFile& dex_file_;
- bool is_static_ = true;
friend class ClassAccessor;
};
@@ -170,10 +144,11 @@ class ClassAccessor {
uint32_t partition_pos,
uint32_t iterator_end,
const uint8_t* ptr_pos)
- : data_(dex_file, ptr_pos),
+ : data_(dex_file),
position_(position),
partition_pos_(partition_pos),
- iterator_end_(iterator_end) {
+ iterator_end_(iterator_end),
+ ptr_pos_(ptr_pos) {
ReadData();
}
@@ -230,7 +205,8 @@ class ClassAccessor {
if (position_ == partition_pos_) {
data_.NextSection();
}
- data_.Read();
+ DCHECK(ptr_pos_ != nullptr);
+ ptr_pos_ = data_.Read(ptr_pos_);
}
}
@@ -241,6 +217,8 @@ class ClassAccessor {
const uint32_t partition_pos_;
// At iterator_end_, the iterator is no longer valid.
const uint32_t iterator_end_;
+ // Internal data pointer.
+ const uint8_t* ptr_pos_;
};
// Not explicit specifically for range-based loops.
@@ -274,21 +252,9 @@ class ClassAccessor {
// Return the iteration range for all the fields.
IterationRange<DataIterator<Field>> GetFields() const;
- // Return the iteration range for all the static fields.
- IterationRange<DataIterator<Field>> GetStaticFields() const;
-
- // Return the iteration range for all the instance fields.
- IterationRange<DataIterator<Field>> GetInstanceFields() const;
-
// Return the iteration range for all the methods.
IterationRange<DataIterator<Method>> GetMethods() const;
- // Return the iteration range for the direct methods.
- IterationRange<DataIterator<Method>> GetDirectMethods() const;
-
- // Return the iteration range for the virtual methods.
- IterationRange<DataIterator<Method>> GetVirtualMethods() const;
-
uint32_t NumStaticFields() const {
return num_static_fields_;
}
@@ -297,10 +263,6 @@ class ClassAccessor {
return num_instance_fields_;
}
- uint32_t NumFields() const {
- return NumStaticFields() + NumInstanceFields();
- }
-
uint32_t NumDirectMethods() const {
return num_direct_methods_;
}
@@ -323,22 +285,14 @@ class ClassAccessor {
return dex_file_;
}
- bool HasClassData() const {
- return ptr_pos_ != nullptr;
- }
-
protected:
// Template visitor to reduce copy paste for visiting elements.
// No thread safety analysis since the visitor may require capabilities.
template <typename DataType, typename Visitor>
- void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const
- NO_THREAD_SAFETY_ANALYSIS;
-
- // Return an iteration range for the first <count> fields.
- IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const;
-
- // Return an iteration range for the first <count> methods.
- IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const;
+ const uint8_t* VisitMembers(size_t count,
+ const Visitor& visitor,
+ const uint8_t* ptr,
+ DataType* data) const NO_THREAD_SAFETY_ANALYSIS;
const DexFile& dex_file_;
const dex::TypeIndex descriptor_index_ = {};
diff --git a/libdexfile/dex/class_accessor_test.cc b/libdexfile/dex/class_accessor_test.cc
index d0533c1811..95380d8140 100644
--- a/libdexfile/dex/class_accessor_test.cc
+++ b/libdexfile/dex/class_accessor_test.cc
@@ -38,27 +38,18 @@ TEST_F(ClassAccessorTest, TestVisiting) {
auto fields = accessor.GetFields();
auto method_it = methods.begin();
auto field_it = fields.begin();
- auto instance_fields = accessor.GetInstanceFields();
- auto instance_field_it = instance_fields.begin();
accessor.VisitFieldsAndMethods(
// Static fields.
[&](const ClassAccessor::Field& field) {
- EXPECT_TRUE(field.IsStatic());
- EXPECT_TRUE(field_it->IsStatic());
EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
++field_it;
},
// Instance fields.
[&](const ClassAccessor::Field& field) {
- EXPECT_FALSE(field.IsStatic());
- EXPECT_FALSE(field_it->IsStatic());
EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
- EXPECT_EQ(field.GetIndex(), instance_field_it->GetIndex());
- EXPECT_EQ(field.GetAccessFlags(), instance_field_it->GetAccessFlags());
++field_it;
- ++instance_field_it;
},
// Direct methods.
[&](const ClassAccessor::Method& method) {
@@ -80,7 +71,6 @@ TEST_F(ClassAccessorTest, TestVisiting) {
});
ASSERT_TRUE(field_it == fields.end());
ASSERT_TRUE(method_it == methods.end());
- ASSERT_TRUE(instance_field_it == instance_fields.end());
}
EXPECT_EQ(class_def_idx, dex_file->NumClassDefs());
}
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index f570158dfb..9de260c862 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -45,18 +45,19 @@ static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex
static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
-void DexFile::UnHideAccessFlags(uint8_t* data_ptr,
- uint32_t new_access_flags,
- bool is_method) {
+void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) {
+ uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer());
+ uint32_t new_flag = class_it.GetMemberAccessFlags();
+ bool is_method = class_it.IsAtMethod();
// Go back 1 uleb to start.
- data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
+ data = ReverseSearchUnsignedLeb128(data);
if (is_method) {
// Methods have another uleb field before the access flags
- data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
+ data = ReverseSearchUnsignedLeb128(data);
}
- DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data_ptr)),
- new_access_flags);
- UpdateUnsignedLeb128(data_ptr, new_access_flags);
+ DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
+ new_flag);
+ UpdateUnsignedLeb128(data, new_flag);
}
uint32_t DexFile::CalculateChecksum() const {
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index ed219808d2..f1f8b505bd 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -1010,8 +1010,8 @@ class DexFile {
return container_.get();
}
- // Changes the dex class data pointed to by data_ptr it to not have any hiddenapi flags.
- static void UnHideAccessFlags(uint8_t* data_ptr, uint32_t new_access_flags, bool is_method);
+ // 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;
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index a660fb56c4..fcbafe7e71 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -31,7 +31,6 @@
#include "base/leb128.h"
#include "fixed_up_dex_file.h"
-#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_file_verifier.h"
@@ -52,12 +51,14 @@ static void RecomputeDexChecksum(art::DexFile* dex_file) {
}
static void UnhideApis(const art::DexFile& target_dex_file) {
- for (art::ClassAccessor accessor : target_dex_file.GetClasses()) {
- for (const art::ClassAccessor::Field& field : accessor.GetFields()) {
- field.UnHideAccessFlags();
- }
- for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
- method.UnHideAccessFlags();
+ for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
+ const uint8_t* class_data = target_dex_file.GetClassData(target_dex_file.GetClassDef(i));
+ if (class_data != nullptr) {
+ for (art::ClassDataItemIterator class_it(target_dex_file, class_data);
+ class_it.HasNext();
+ class_it.Next()) {
+ art::DexFile::UnHideAccessFlags(class_it);
+ }
}
}
}
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 4e9f3c52e2..151c36f3bc 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -26,7 +26,6 @@
#include "class_linker-inl.h"
#include "class_root.h"
#include "debugger.h"
-#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -435,14 +434,28 @@ bool ArtMethod::IsPolymorphicSignature() {
static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
uint16_t class_def_idx,
uint32_t method_idx) {
- ClassAccessor accessor(dex_file, dex_file.GetClassDef(class_def_idx));
- uint32_t class_def_method_index = 0u;
- for (const ClassAccessor::Method& method : accessor.GetMethods()) {
- if (method.GetIndex() == method_idx) {
+ const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx);
+ const uint8_t* class_data = dex_file.GetClassData(class_def);
+ CHECK(class_data != nullptr);
+ ClassDataItemIterator it(dex_file, class_data);
+ it.SkipAllFields();
+ // Process methods
+ size_t class_def_method_index = 0;
+ while (it.HasNextDirectMethod()) {
+ if (it.GetMemberIndex() == method_idx) {
return class_def_method_index;
}
class_def_method_index++;
+ it.Next();
}
+ while (it.HasNextVirtualMethod()) {
+ if (it.GetMemberIndex() == method_idx) {
+ return class_def_method_index;
+ }
+ class_def_method_index++;
+ it.Next();
+ }
+ DCHECK(!it.HasNext());
LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
UNREACHABLE();
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d6ac3bad52..095272394a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,7 +56,6 @@
#include "compiler_callbacks.h"
#include "debug_print.h"
#include "debugger.h"
-#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -2735,50 +2734,52 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) {
+ const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
size_t num_ref = 0;
size_t num_8 = 0;
size_t num_16 = 0;
size_t num_32 = 0;
size_t num_64 = 0;
- ClassAccessor accessor(dex_file, dex_class_def);
- // We allow duplicate definitions of the same field in a class_data_item
- // but ignore the repeated indexes here, b/21868015.
- uint32_t last_field_idx = dex::kDexNoIndex;
- for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
- uint32_t field_idx = field.GetIndex();
- // Ordering enforced by DexFileVerifier.
- DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
- if (UNLIKELY(field_idx == last_field_idx)) {
- continue;
- }
- last_field_idx = field_idx;
- const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
- char c = descriptor[0];
- switch (c) {
- case 'L':
- case '[':
- num_ref++;
- break;
- case 'J':
- case 'D':
- num_64++;
- break;
- case 'I':
- case 'F':
- num_32++;
- break;
- case 'S':
- case 'C':
- num_16++;
- break;
- case 'B':
- case 'Z':
- num_8++;
- break;
- default:
- LOG(FATAL) << "Unknown descriptor: " << c;
- UNREACHABLE();
+ if (class_data != nullptr) {
+ // We allow duplicate definitions of the same field in a class_data_item
+ // but ignore the repeated indexes here, b/21868015.
+ uint32_t last_field_idx = dex::kDexNoIndex;
+ for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ // Ordering enforced by DexFileVerifier.
+ DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
+ if (UNLIKELY(field_idx == last_field_idx)) {
+ continue;
+ }
+ last_field_idx = field_idx;
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
+ const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
+ char c = descriptor[0];
+ switch (c) {
+ case 'L':
+ case '[':
+ num_ref++;
+ break;
+ case 'J':
+ case 'D':
+ num_64++;
+ break;
+ case 'I':
+ case 'F':
+ num_32++;
+ break;
+ case 'S':
+ case 'C':
+ num_16++;
+ break;
+ case 'B':
+ case 'Z':
+ num_8++;
+ break;
+ default:
+ LOG(FATAL) << "Unknown descriptor: " << c;
+ UNREACHABLE();
+ }
}
}
return mirror::Class::ComputeClassSize(false,
@@ -2876,15 +2877,17 @@ void ClassLinker::FixupStaticTrampolines(ObjPtr<mirror::Class> klass) {
const DexFile& dex_file = klass->GetDexFile();
const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
- ClassAccessor accessor(dex_file, *dex_class_def);
+ const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
// There should always be class data if there were direct methods.
- CHECK(accessor.HasClassData()) << klass->PrettyDescriptor();
+ CHECK(class_data != nullptr) << klass->PrettyDescriptor();
+ ClassDataItemIterator it(dex_file, class_data);
+ it.SkipAllFields();
bool has_oat_class;
OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file,
klass->GetDexClassDefIndex(),
&has_oat_class);
// Link the code of methods skipped by LinkCode.
- for (size_t method_index = 0; method_index < accessor.NumDirectMethods(); ++method_index) {
+ for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
if (!method->IsStatic()) {
// Only update static methods.
@@ -2993,6 +2996,17 @@ void ClassLinker::SetupClass(const DexFile& dex_file,
klass->SetDexTypeIndex(dex_class_def.class_idx_);
}
+void ClassLinker::LoadClass(Thread* self,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def,
+ Handle<mirror::Class> klass) {
+ const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
+ if (class_data == nullptr) {
+ return; // no fields or methods - for example a marker interface
+ }
+ LoadClassMembers(self, dex_file, class_data, klass);
+}
+
LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
LinearAlloc* allocator,
size_t length) {
@@ -3051,15 +3065,10 @@ LinearAlloc* ClassLinker::GetOrCreateAllocatorForClassLoader(ObjPtr<mirror::Clas
return allocator;
}
-void ClassLinker::LoadClass(Thread* self,
- const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def,
- Handle<mirror::Class> klass) {
- ClassAccessor accessor(dex_file, dex_class_def);
- if (!accessor.HasClassData()) {
- return;
- }
- Runtime* const runtime = Runtime::Current();
+void ClassLinker::LoadClassMembers(Thread* self,
+ const DexFile& dex_file,
+ const uint8_t* class_data,
+ Handle<mirror::Class> klass) {
{
// Note: We cannot have thread suspension until the field and method arrays are setup or else
// Class::VisitFieldRoots may miss some fields or methods.
@@ -3068,79 +3077,45 @@ void ClassLinker::LoadClass(Thread* self,
// We allow duplicate definitions of the same field in a class_data_item
// but ignore the repeated indexes here, b/21868015.
LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
+ ClassDataItemIterator it(dex_file, class_data);
LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
allocator,
- accessor.NumStaticFields());
+ it.NumStaticFields());
+ size_t num_sfields = 0;
+ uint32_t last_field_idx = 0u;
+ for (; it.HasNextStaticField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {
+ DCHECK_LT(num_sfields, it.NumStaticFields());
+ LoadField(it, klass, &sfields->At(num_sfields));
+ ++num_sfields;
+ last_field_idx = field_idx;
+ }
+ }
+
+ // Load instance fields.
LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
allocator,
- accessor.NumInstanceFields());
- size_t num_sfields = 0u;
+ it.NumInstanceFields());
size_t num_ifields = 0u;
- uint32_t last_static_field_idx = 0u;
- uint32_t last_instance_field_idx = 0u;
-
- // Methods
- bool has_oat_class = false;
- const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
- ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
- : OatFile::OatClass::Invalid();
- const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
- klass->SetMethodsPtr(
- AllocArtMethodArray(self, allocator, accessor.NumMethods()),
- accessor.NumDirectMethods(),
- accessor.NumVirtualMethods());
- size_t class_def_method_index = 0;
- uint32_t last_dex_method_index = dex::kDexNoIndex;
- size_t last_class_def_method_index = 0;
+ last_field_idx = 0u;
+ for (; it.HasNextInstanceField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
+ DCHECK_LT(num_ifields, it.NumInstanceFields());
+ LoadField(it, klass, &ifields->At(num_ifields));
+ ++num_ifields;
+ last_field_idx = field_idx;
+ }
+ }
- // Use the visitor since the ranged based loops are bit slower from seeking. Seeking to the
- // methods needs to decode all of the fields.
- accessor.VisitFieldsAndMethods([&](
- const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
- uint32_t field_idx = field.GetIndex();
- DCHECK_GE(field_idx, last_static_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_sfields == 0 || LIKELY(field_idx > last_static_field_idx)) {
- LoadField(field, klass, &sfields->At(num_sfields));
- ++num_sfields;
- last_static_field_idx = field_idx;
- }
- }, [&](const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
- uint32_t field_idx = field.GetIndex();
- DCHECK_GE(field_idx, last_instance_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_ifields == 0 || LIKELY(field_idx > last_instance_field_idx)) {
- LoadField(field, klass, &ifields->At(num_ifields));
- ++num_ifields;
- last_instance_field_idx = field_idx;
- }
- }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
- ArtMethod* art_method = klass->GetDirectMethodUnchecked(class_def_method_index,
- image_pointer_size_);
- LoadMethod(dex_file, method, klass, art_method);
- LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
- uint32_t it_method_index = method.GetIndex();
- if (last_dex_method_index == it_method_index) {
- // duplicate case
- art_method->SetMethodIndex(last_class_def_method_index);
- } else {
- art_method->SetMethodIndex(class_def_method_index);
- last_dex_method_index = it_method_index;
- last_class_def_method_index = class_def_method_index;
- }
- ++class_def_method_index;
- }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
- ArtMethod* art_method = klass->GetVirtualMethodUnchecked(
- class_def_method_index - accessor.NumDirectMethods(),
- image_pointer_size_);
- LoadMethod(dex_file, method, klass, art_method);
- LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
- ++class_def_method_index;
- });
-
- if (UNLIKELY(num_ifields + num_sfields != accessor.NumFields())) {
+ if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
+ UNLIKELY(num_ifields != it.NumInstanceFields())) {
LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
- << " (unique static fields: " << num_sfields << "/" << accessor.NumStaticFields()
- << ", unique instance fields: " << num_ifields << "/" << accessor.NumInstanceFields()
- << ")";
+ << " (unique static fields: " << num_sfields << "/" << it.NumStaticFields()
+ << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")";
// NOTE: Not shrinking the over-allocated sfields/ifields, just setting size.
if (sfields != nullptr) {
sfields->SetSize(num_sfields);
@@ -3154,49 +3129,87 @@ void ClassLinker::LoadClass(Thread* self,
DCHECK_EQ(klass->NumStaticFields(), num_sfields);
klass->SetIFieldsPtr(ifields);
DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
+ // Load methods.
+ bool has_oat_class = false;
+ const OatFile::OatClass oat_class =
+ (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
+ ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
+ : OatFile::OatClass::Invalid();
+ const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
+ klass->SetMethodsPtr(
+ AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
+ it.NumDirectMethods(),
+ it.NumVirtualMethods());
+ size_t class_def_method_index = 0;
+ uint32_t last_dex_method_index = dex::kDexNoIndex;
+ size_t last_class_def_method_index = 0;
+ // TODO These should really use the iterators.
+ for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
+ ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
+ LoadMethod(dex_file, it, klass, method);
+ LinkCode(this, method, oat_class_ptr, class_def_method_index);
+ uint32_t it_method_index = it.GetMemberIndex();
+ if (last_dex_method_index == it_method_index) {
+ // duplicate case
+ method->SetMethodIndex(last_class_def_method_index);
+ } else {
+ method->SetMethodIndex(class_def_method_index);
+ last_dex_method_index = it_method_index;
+ last_class_def_method_index = class_def_method_index;
+ }
+ class_def_method_index++;
+ }
+ for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
+ ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
+ LoadMethod(dex_file, it, klass, method);
+ DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
+ LinkCode(this, method, oat_class_ptr, class_def_method_index);
+ class_def_method_index++;
+ }
+ DCHECK(!it.HasNext());
}
// Ensure that the card is marked so that remembered sets pick up native roots.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
self->AllowThreadSuspension();
}
-void ClassLinker::LoadField(const ClassAccessor::Field& field,
+void ClassLinker::LoadField(const ClassDataItemIterator& it,
Handle<mirror::Class> klass,
ArtField* dst) {
- const uint32_t field_idx = field.GetIndex();
+ const uint32_t field_idx = it.GetMemberIndex();
dst->SetDexFieldIndex(field_idx);
dst->SetDeclaringClass(klass.Get());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = field.GetAccessFlags();
+ uint32_t access_flags = it.GetFieldAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
}
dst->SetAccessFlags(access_flags);
}
void ClassLinker::LoadMethod(const DexFile& dex_file,
- const ClassAccessor::Method& method,
+ const ClassDataItemIterator& it,
Handle<mirror::Class> klass,
ArtMethod* dst) {
- const uint32_t dex_method_idx = method.GetIndex();
+ uint32_t dex_method_idx = it.GetMemberIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
ScopedAssertNoThreadSuspension ants("LoadMethod");
dst->SetDexMethodIndex(dex_method_idx);
dst->SetDeclaringClass(klass.Get());
- dst->SetCodeItemOffset(method.GetCodeItemOffset());
+ dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = method.GetAccessFlags();
+ uint32_t access_flags = it.GetMethodAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
}
if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
@@ -4759,29 +4772,24 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
this,
*dex_class_def);
const DexFile& dex_file = *dex_cache->GetDexFile();
-
+ const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
+ ClassDataItemIterator field_it(dex_file, class_data);
if (value_it.HasNext()) {
- ClassAccessor accessor(dex_file, *dex_class_def);
+ DCHECK(field_it.HasNextStaticField());
CHECK(can_init_statics);
- for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
- if (!value_it.HasNext()) {
- break;
- }
- ArtField* art_field = ResolveField(field.GetIndex(),
- dex_cache,
- class_loader,
- /* is_static */ true);
+ for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
+ ArtField* field = ResolveField(
+ field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true);
if (Runtime::Current()->IsActiveTransaction()) {
- value_it.ReadValueToField<true>(art_field);
+ value_it.ReadValueToField<true>(field);
} else {
- value_it.ReadValueToField<false>(art_field);
+ value_it.ReadValueToField<false>(field);
}
if (self->IsExceptionPending()) {
break;
}
- value_it.Next();
+ DCHECK(!value_it.HasNext() || field_it.HasNextStaticField());
}
- DCHECK(self->IsExceptionPending() || !value_it.HasNext());
}
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 1912d21d98..1f94c43408 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -27,7 +27,6 @@
#include "base/enums.h"
#include "base/macros.h"
#include "base/mutex.h"
-#include "dex/class_accessor.h"
#include "dex/dex_cache_resolved_classes.h"
#include "dex/dex_file.h"
#include "dex/dex_file_types.h"
@@ -824,14 +823,18 @@ class ClassLinker {
const DexFile::ClassDef& dex_class_def,
Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
+ void LoadClassMembers(Thread* self,
+ const DexFile& dex_file,
+ const uint8_t* class_data,
+ Handle<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_);
- void LoadField(const ClassAccessor::Field& field, Handle<mirror::Class> klass, ArtField* dst)
+ void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtField* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
void LoadMethod(const DexFile& dex_file,
- const ClassAccessor::Method& method,
- Handle<mirror::Class> klass,
- ArtMethod* dst)
+ const ClassDataItemIterator& it,
+ Handle<mirror::Class> klass, ArtMethod* dst)
REQUIRES_SHARED(Locks::mutator_lock_);
void FixupStaticTrampolines(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index c9deb526c2..6c820190b4 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -32,7 +32,6 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version);
#include "class_linker-inl.h"
#include "common_throws.h"
#include "debugger.h"
-#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
#include "gc/accounting/card_table-inl.h"
@@ -574,12 +573,30 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) {
}
if (kPreloadDexCachesFieldsAndMethods) {
- for (ClassAccessor accessor : dex_file->GetClasses()) {
- for (const ClassAccessor::Field& field : accessor.GetFields()) {
- PreloadDexCachesResolveField(dex_cache, field.GetIndex(), field.IsStatic());
+ 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);
+ const uint8_t* class_data = dex_file->GetClassData(class_def);
+ if (class_data == nullptr) {
+ continue;
}
- for (const ClassAccessor::Method& method : accessor.GetMethods()) {
- PreloadDexCachesResolveMethod(dex_cache, method.GetIndex());
+ ClassDataItemIterator it(*dex_file, class_data);
+ for (; it.HasNextStaticField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ PreloadDexCachesResolveField(dex_cache, field_idx, true);
+ }
+ for (; it.HasNextInstanceField(); it.Next()) {
+ uint32_t field_idx = it.GetMemberIndex();
+ PreloadDexCachesResolveField(dex_cache, field_idx, false);
+ }
+ for (; it.HasNextDirectMethod(); it.Next()) {
+ uint32_t method_idx = it.GetMemberIndex();
+ PreloadDexCachesResolveMethod(dex_cache, method_idx);
+ }
+ for (; it.HasNextVirtualMethod(); it.Next()) {
+ uint32_t method_idx = it.GetMemberIndex();
+ PreloadDexCachesResolveMethod(dex_cache, method_idx);
}
}
}
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index e2f42c937d..838d7f14bc 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -28,7 +28,6 @@
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "dex/art_dex_file_loader.h"
-#include "dex/class_accessor-inl.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "dex/hidden_api_access_flags.h"
@@ -284,26 +283,31 @@ void VdexFile::UnquickenDexFile(const DexFile& target_dex_file,
std::unordered_set<const DexFile::CodeItem*> unquickened_code_item;
CompactOffsetTable::Accessor accessor(GetQuickenInfoOffsetTable(source_dex_begin,
quickening_info));
- for (ClassAccessor class_accessor : target_dex_file.GetClasses()) {
- for (const ClassAccessor::Method& method : class_accessor.GetMethods()) {
- const DexFile::CodeItem* code_item = method.GetCodeItem();
- if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
- const uint32_t offset = accessor.GetOffset(method.GetIndex());
- // Offset being 0 means not quickened.
- if (offset != 0u) {
- ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
- optimizer::ArtDecompileDEX(
- target_dex_file,
- *code_item,
- quicken_data,
- decompile_return_instruction);
+ for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
+ const DexFile::ClassDef& class_def = target_dex_file.GetClassDef(i);
+ const uint8_t* class_data = target_dex_file.GetClassData(class_def);
+ if (class_data != nullptr) {
+ for (ClassDataItemIterator class_it(target_dex_file, class_data);
+ class_it.HasNext();
+ class_it.Next()) {
+ if (class_it.IsAtMethod()) {
+ const DexFile::CodeItem* code_item = class_it.GetMethodCodeItem();
+ if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
+ const uint32_t offset = accessor.GetOffset(class_it.GetMemberIndex());
+ // Offset being 0 means not quickened.
+ if (offset != 0u) {
+ ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
+ optimizer::ArtDecompileDEX(
+ target_dex_file,
+ *code_item,
+ quicken_data,
+ decompile_return_instruction);
+ }
+ }
}
- method.UnHideAccessFlags();
+ DexFile::UnHideAccessFlags(class_it);
}
}
- for (const ClassAccessor::Field& field : class_accessor.GetFields()) {
- field.UnHideAccessFlags();
- }
}
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 8169568413..cc71dc5f84 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -35,7 +35,6 @@
#include "class_linker.h"
#include "class_root.h"
#include "compiler_callbacks.h"
-#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -191,6 +190,11 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
error);
}
+template <bool kDirect>
+static bool HasNextMethod(ClassDataItemIterator* it) {
+ return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod();
+}
+
static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) {
static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure
&& FailureKind::kSoftFailure < FailureKind::kHardFailure,
@@ -203,51 +207,45 @@ void MethodVerifier::FailureData::Merge(const MethodVerifier::FailureData& fd) {
types |= fd.types;
}
-FailureKind MethodVerifier::VerifyClass(Thread* self,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const DexFile::ClassDef& class_def,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- std::string* error) {
- SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+template <bool kDirect>
+MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self,
+ ClassLinker* linker,
+ const DexFile* dex_file,
+ const DexFile::ClassDef& class_def,
+ ClassDataItemIterator* it,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ bool need_precise_constants,
+ std::string* error_string) {
+ DCHECK(it != nullptr);
- // A class must not be abstract and final.
- if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
- *error = "Verifier rejected class ";
- *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error += ": class is abstract and final.";
- return FailureKind::kHardFailure;
- }
-
- ClassAccessor accessor(*dex_file, class_def);
-
- int64_t previous_method_idx[2] = { -1, -1 };
MethodVerifier::FailureData failure_data;
- ClassLinker* const linker = Runtime::Current()->GetClassLinker();
- for (const ClassAccessor::Method& method : accessor.GetMethods()) {
- int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
+ int64_t previous_method_idx = -1;
+ while (HasNextMethod<kDirect>(it)) {
self->AllowThreadSuspension();
- const uint32_t method_idx = method.GetIndex();
- if (method_idx == *previous_idx) {
+ uint32_t method_idx = it->GetMemberIndex();
+ if (method_idx == previous_method_idx) {
// smali can create dex files with two encoded_methods sharing the same method_idx
// http://code.google.com/p/smali/issues/detail?id=119
+ it->Next();
continue;
}
- *previous_idx = method_idx;
- const InvokeType type = method.GetInvokeType(class_def.access_flags_);
- ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+ previous_method_idx = method_idx;
+ InvokeType type = it->GetMethodInvokeType(class_def);
+ ArtMethod* method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
method_idx, dex_cache, class_loader, /* referrer */ nullptr, type);
- if (resolved_method == nullptr) {
+ if (method == nullptr) {
DCHECK(self->IsExceptionPending());
// We couldn't resolve the method, but continue regardless.
self->ClearException();
} else {
- DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
+ DCHECK(method->GetDeclaringClassUnchecked() != nullptr) << type;
}
+ StackHandleScope<1> hs(self);
std::string hard_failure_msg;
MethodVerifier::FailureData result = VerifyMethod(self,
method_idx,
@@ -255,39 +253,99 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
dex_cache,
class_loader,
class_def,
- method.GetCodeItem(),
- resolved_method,
- method.GetAccessFlags(),
+ it->GetMethodCodeItem(),
+ method,
+ it->GetMethodAccessFlags(),
callbacks,
allow_soft_failures,
log_level,
- /*need_precise_constants*/ false,
+ need_precise_constants,
&hard_failure_msg);
if (result.kind == FailureKind::kHardFailure) {
if (failure_data.kind == FailureKind::kHardFailure) {
// If we logged an error before, we need a newline.
- *error += "\n";
+ *error_string += "\n";
} else {
// If we didn't log a hard failure before, print the header of the message.
- *error += "Verifier rejected class ";
- *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error += ":";
+ *error_string += "Verifier rejected class ";
+ *error_string += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error_string += ":";
}
- *error += " ";
- *error += hard_failure_msg;
+ *error_string += " ";
+ *error_string += hard_failure_msg;
}
failure_data.Merge(result);
+ it->Next();
+ }
+
+ return failure_data;
+}
+
+FailureKind MethodVerifier::VerifyClass(Thread* self,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const DexFile::ClassDef& class_def,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ std::string* error) {
+ SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+
+ // A class must not be abstract and final.
+ if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
+ *error = "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ": class is abstract and final.";
+ return FailureKind::kHardFailure;
}
- if (failure_data.kind == FailureKind::kNoFailure) {
+ const uint8_t* class_data = dex_file->GetClassData(class_def);
+ if (class_data == nullptr) {
+ // empty class, probably a marker interface
+ return FailureKind::kNoFailure;
+ }
+ ClassDataItemIterator it(*dex_file, class_data);
+ it.SkipAllFields();
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ // Direct methods.
+ MethodVerifier::FailureData data1 = VerifyMethods<true>(self,
+ linker,
+ dex_file,
+ class_def,
+ &it,
+ dex_cache,
+ class_loader,
+ callbacks,
+ allow_soft_failures,
+ log_level,
+ false /* need precise constants */,
+ error);
+ // Virtual methods.
+ MethodVerifier::FailureData data2 = VerifyMethods<false>(self,
+ linker,
+ dex_file,
+ class_def,
+ &it,
+ dex_cache,
+ class_loader,
+ callbacks,
+ allow_soft_failures,
+ log_level,
+ false /* need precise constants */,
+ error);
+
+ data1.Merge(data2);
+
+ if (data1.kind == FailureKind::kNoFailure) {
return FailureKind::kNoFailure;
} else {
- if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
+ if ((data1.types & VERIFY_ERROR_LOCKING) != 0) {
// Print a warning about expected slow-down. Use a string temporary to print one contiguous
// warning.
std::string tmp =
StringPrintf("Class %s failed lock verification and will run slower.",
- PrettyDescriptor(accessor.GetDescriptor()).c_str());
+ PrettyDescriptor(dex_file->GetClassDescriptor(class_def)).c_str());
if (!gPrintedDxMonitorText) {
tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
"and incorrect proguard optimizations.";
@@ -295,7 +353,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
}
LOG(WARNING) << tmp;
}
- return failure_data.kind;
+ return data1.kind;
}
}
@@ -1866,11 +1924,15 @@ bool MethodVerifier::CodeFlowVerifyMethod() {
static uint32_t GetFirstFinalInstanceFieldIndex(const DexFile& dex_file, dex::TypeIndex type_idx) {
const DexFile::ClassDef* class_def = dex_file.FindClassDef(type_idx);
DCHECK(class_def != nullptr);
- ClassAccessor accessor(dex_file, *class_def);
- for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
- if (field.IsFinal()) {
- return field.GetIndex();
- }
+ const uint8_t* class_data = dex_file.GetClassData(*class_def);
+ DCHECK(class_data != nullptr);
+ ClassDataItemIterator it(dex_file, class_data);
+ it.SkipStaticFields();
+ while (it.HasNextInstanceField()) {
+ if ((it.GetFieldAccessFlags() & kAccFinal) != 0) {
+ return it.GetMemberIndex();
+ }
+ it.Next();
}
return dex::kDexNoIndex;
}
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index c7368d7b39..b2adc62a97 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -275,6 +275,23 @@ class MethodVerifier {
void Merge(const FailureData& src);
};
+ // Verify all direct or virtual methods of a class. The method assumes that the iterator is
+ // positioned correctly, and the iterator will be updated.
+ template <bool kDirect>
+ static FailureData VerifyMethods(Thread* self,
+ ClassLinker* linker,
+ const DexFile* dex_file,
+ const DexFile::ClassDef& class_def,
+ ClassDataItemIterator* it,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ bool need_precise_constants,
+ std::string* error_string)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
/*
* Perform verification on a single method.
*