ART: Refactor class-def retrieval
Peel the first loop iteration to avoid excessive branches and loads.
Bug: 78568168
Test: m test-art-host
Change-Id: I22f403254b01d34837dde1decc05e2d00700ffeb
diff --git a/libdexfile/dex/dex_file_verifier.cc b/libdexfile/dex/dex_file_verifier.cc
index e0bfdcf..3f72a25 100644
--- a/libdexfile/dex/dex_file_verifier.cc
+++ b/libdexfile/dex/dex_file_verifier.cc
@@ -994,31 +994,16 @@
return false;
}
-bool DexFileVerifier::CheckOrderAndGetClassDef(bool is_field,
- const char* type_descr,
- uint32_t curr_index,
- uint32_t prev_index,
- bool* have_class,
- dex::TypeIndex* class_type_index,
- const DexFile::ClassDef** class_def) {
- if (curr_index < prev_index) {
+bool DexFileVerifier::CheckOrder(const char* type_descr,
+ uint32_t curr_index,
+ uint32_t prev_index) {
+ if (UNLIKELY(curr_index < prev_index)) {
ErrorStringPrintf("out-of-order %s indexes %" PRIu32 " and %" PRIu32,
type_descr,
prev_index,
curr_index);
return false;
}
-
- if (!*have_class) {
- *have_class = FindClassIndexAndDef(curr_index, is_field, class_type_index, class_def);
- if (!*have_class) {
- // Should have really found one.
- ErrorStringPrintf("could not find declaring class for %s index %" PRIu32,
- type_descr,
- curr_index);
- return false;
- }
- }
return true;
}
@@ -1123,20 +1108,29 @@
dex::TypeIndex* class_type_index,
const DexFile::ClassDef** class_def) {
DCHECK(it != nullptr);
+ constexpr const char* kTypeDescr = kStatic ? "static field" : "instance field";
+
// These calls use the raw access flags to check whether the whole dex field is valid.
+
+ if (!*have_class && (kStatic ? it->HasNextStaticField() : it->HasNextInstanceField())) {
+ *have_class = FindClassIndexAndDef(it->GetMemberIndex(), true, class_type_index, class_def);
+ if (!*have_class) {
+ // Should have really found one.
+ ErrorStringPrintf("could not find declaring class for %s index %" PRIu32,
+ kTypeDescr,
+ it->GetMemberIndex());
+ return false;
+ }
+ }
+ DCHECK(*class_def != nullptr ||
+ !(kStatic ? it->HasNextStaticField() : it->HasNextInstanceField()));
+
uint32_t prev_index = 0;
for (; kStatic ? it->HasNextStaticField() : it->HasNextInstanceField(); it->Next()) {
uint32_t curr_index = it->GetMemberIndex();
- if (!CheckOrderAndGetClassDef(true,
- kStatic ? "static field" : "instance field",
- curr_index,
- prev_index,
- have_class,
- class_type_index,
- class_def)) {
+ if (!CheckOrder(kTypeDescr, curr_index, prev_index)) {
return false;
}
- DCHECK(class_def != nullptr);
if (!CheckClassDataItemField(curr_index,
it->GetRawMemberAccessFlags(),
(*class_def)->access_flags_,
@@ -1158,19 +1152,28 @@
bool* have_class,
dex::TypeIndex* class_type_index,
const DexFile::ClassDef** class_def) {
+ DCHECK(it != nullptr);
+ constexpr const char* kTypeDescr = kDirect ? "direct method" : "virtual method";
+
+ if (!*have_class && (kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod())) {
+ *have_class = FindClassIndexAndDef(it->GetMemberIndex(), false, class_type_index, class_def);
+ if (!*have_class) {
+ // Should have really found one.
+ ErrorStringPrintf("could not find declaring class for %s index %" PRIu32,
+ kTypeDescr,
+ it->GetMemberIndex());
+ return false;
+ }
+ }
+ DCHECK(*class_def != nullptr ||
+ !(kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod()));
+
uint32_t prev_index = 0;
for (; kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod(); it->Next()) {
uint32_t curr_index = it->GetMemberIndex();
- if (!CheckOrderAndGetClassDef(false,
- kDirect ? "direct method" : "virtual method",
- curr_index,
- prev_index,
- have_class,
- class_type_index,
- class_def)) {
+ if (!CheckOrder(kTypeDescr, curr_index, prev_index)) {
return false;
}
- DCHECK(class_def != nullptr);
if (!CheckClassDataItemMethod(curr_index,
it->GetRawMemberAccessFlags(),
(*class_def)->access_flags_,
diff --git a/libdexfile/dex/dex_file_verifier.h b/libdexfile/dex/dex_file_verifier.h
index 3bddc77..4b73363 100644
--- a/libdexfile/dex/dex_file_verifier.h
+++ b/libdexfile/dex/dex_file_verifier.h
@@ -87,13 +87,8 @@
uint32_t code_offset,
ClassDataItemIterator* direct_it,
bool expect_direct);
- bool CheckOrderAndGetClassDef(bool is_field,
- const char* type_descr,
- uint32_t curr_index,
- uint32_t prev_index,
- bool* have_class,
- dex::TypeIndex* class_type_index,
- const DexFile::ClassDef** class_def);
+ ALWAYS_INLINE
+ bool CheckOrder(const char* type_descr, uint32_t curr_index, uint32_t prev_index);
bool CheckStaticFieldTypes(const DexFile::ClassDef* class_def);
bool CheckPadding(size_t offset, uint32_t aligned_offset, DexFile::MapItemType type);