diff options
| author | 2016-11-17 13:08:35 -0800 | |
|---|---|---|
| committer | 2016-11-21 13:28:23 -0800 | |
| commit | 32b50302d9826430013e008b45d5c71e6b7a2469 (patch) | |
| tree | 210a7c575cc246787afdbbd988a45c8f38b8b169 | |
| parent | a598b869b255b4daeaa34d1dd0939222a3a791b7 (diff) | |
Check same dex file for finding class descriptor string id
Use ClassDef for finding same dex file class descriptor string id
for vdex. Removes some calls to FindStringId, the remaining calls to
FindStringId are due to multidex or referring to types in the boot
class path.
Also check method index slot to see if we get lucky.
Host perf:
DexFile::FindStringId: 2.57% -> 0.94%
Not done for fields since these do not seem to reach the FindStringId
case accordingto perf. The remaining calls to FindStringId come from:
100.00% verifier::VerifierDeps::GetClassDescriptorStringId
-> 66.62% verifier::VerifierDeps::AddAssignability
-> 33.38% verifier::VerifierDeps::AddMethodResolution
FB install time: 35.54s -> 34.41s (avg of 40 samples at 960MHZ N6P).
Bug: 32641252
Test: test-art-host
Change-Id: If50408cf1be5c2d2127140780b8d5af66306939c
| -rw-r--r-- | runtime/verifier/verifier_deps.cc | 96 | ||||
| -rw-r--r-- | runtime/verifier/verifier_deps.h | 15 |
2 files changed, 93 insertions, 18 deletions
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc index 8a0f4cfa31..a65e82b3df 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -16,6 +16,8 @@ #include "verifier_deps.h" +#include <cstring> + #include "compiler_callbacks.h" #include "leb128.h" #include "mirror/class-inl.h" @@ -56,17 +58,80 @@ uint16_t VerifierDeps::GetAccessFlags(T* element) { } } -template <typename T> -uint32_t VerifierDeps::GetDeclaringClassStringId(const DexFile& dex_file, T* element) { +uint32_t VerifierDeps::GetClassDescriptorStringId(const DexFile& dex_file, + ObjPtr<mirror::Class> klass) { + DCHECK(klass != nullptr); + ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache(); + // Array classes do not have a dex cache. + if (!klass->IsArrayClass() && !klass->IsProxyClass()) { + DCHECK(dex_cache != nullptr) << klass->PrettyClass(); + if (dex_cache->GetDexFile() == &dex_file) { + // FindStringId is slow, try to go through the class def if we have one. + const DexFile::ClassDef* class_def = klass->GetClassDef(); + DCHECK(class_def != nullptr) << klass->PrettyClass(); + std::string temp; + const DexFile::TypeId& type_id = dex_file.GetTypeId(class_def->class_idx_); + DCHECK_EQ(GetIdFromString(dex_file, klass->GetDescriptor(&temp)), type_id.descriptor_idx_); + return type_id.descriptor_idx_; + } + } + std::string temp; + return GetIdFromString(dex_file, klass->GetDescriptor(&temp)); +} + +// Try to find the string descriptor of the class. type_idx is a best guess of a matching string id. +static uint32_t TryGetClassDescriptorStringId(const DexFile& dex_file, + dex::TypeIndex type_idx, + ObjPtr<mirror::Class> klass) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (!klass->IsArrayClass()) { + const DexFile::TypeId& type_id = dex_file.GetTypeId(type_idx); + const DexFile& klass_dex = klass->GetDexFile(); + const DexFile::TypeId& klass_type_id = klass_dex.GetTypeId(klass->GetClassDef()->class_idx_); + if (strcmp(dex_file.GetTypeDescriptor(type_id), + klass_dex.GetTypeDescriptor(klass_type_id)) == 0) { + return type_id.descriptor_idx_; + } + } + return DexFile::kDexNoIndex; +} + +uint32_t VerifierDeps::GetMethodDeclaringClassStringId(const DexFile& dex_file, + uint32_t dex_method_index, + ArtMethod* method) { static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant"); - if (element == nullptr) { + if (method == nullptr) { return VerifierDeps::kUnresolvedMarker; - } else { - std::string temp; - uint32_t string_id = GetIdFromString( - dex_file, element->GetDeclaringClass()->GetDescriptor(&temp)); + } + const uint32_t string_id = TryGetClassDescriptorStringId( + dex_file, + dex_file.GetMethodId(dex_method_index).class_idx_, + method->GetDeclaringClass()); + if (string_id != DexFile::kDexNoIndex) { + // Got lucky using the original dex file, return based on the input dex file. + DCHECK_EQ(GetClassDescriptorStringId(dex_file, method->GetDeclaringClass()), string_id); return string_id; } + return GetClassDescriptorStringId(dex_file, method->GetDeclaringClass()); +} + +uint32_t VerifierDeps::GetFieldDeclaringClassStringId(const DexFile& dex_file, + uint32_t dex_field_idx, + ArtField* field) { + static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant"); + if (field == nullptr) { + return VerifierDeps::kUnresolvedMarker; + } + const uint32_t string_id = TryGetClassDescriptorStringId( + dex_file, + dex_file.GetFieldId(dex_field_idx).class_idx_, + field->GetDeclaringClass()); + if (string_id != DexFile::kDexNoIndex) { + // Got lucky using the original dex file, return based on the input dex file. + DCHECK_EQ(GetClassDescriptorStringId(dex_file, field->GetDeclaringClass()), string_id); + return string_id; + } + return GetClassDescriptorStringId(dex_file, field->GetDeclaringClass()); } uint32_t VerifierDeps::GetIdFromString(const DexFile& dex_file, const std::string& str) { @@ -171,8 +236,11 @@ void VerifierDeps::AddFieldResolution(const DexFile& dex_file, } MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_); - dex_deps->fields_.emplace(FieldResolution( - field_idx, GetAccessFlags(field), GetDeclaringClassStringId(dex_file, field))); + dex_deps->fields_.emplace(FieldResolution(field_idx, + GetAccessFlags(field), + GetFieldDeclaringClassStringId(dex_file, + field_idx, + field))); } void VerifierDeps::AddMethodResolution(const DexFile& dex_file, @@ -194,7 +262,7 @@ void VerifierDeps::AddMethodResolution(const DexFile& dex_file, MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_); MethodResolution method_tuple(method_idx, GetAccessFlags(method), - GetDeclaringClassStringId(dex_file, method)); + GetMethodDeclaringClassStringId(dex_file, method_idx, method)); if (resolution_kind == kDirectMethodResolution) { dex_deps->direct_methods_.emplace(method_tuple); } else if (resolution_kind == kVirtualMethodResolution) { @@ -263,12 +331,8 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file, MutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_); // Get string IDs for both descriptors and store in the appropriate set. - - std::string temp1, temp2; - std::string destination_desc(destination->GetDescriptor(&temp1)); - std::string source_desc(source->GetDescriptor(&temp2)); - uint32_t destination_id = GetIdFromString(dex_file, destination_desc); - uint32_t source_id = GetIdFromString(dex_file, source_desc); + uint32_t destination_id = GetClassDescriptorStringId(dex_file, destination); + uint32_t source_id = GetClassDescriptorStringId(dex_file, source); if (is_assignable) { dex_deps->assignable_types_.emplace(TypeAssignability(destination_id, source_id)); diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index 23e22d956d..e35af41e3f 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -232,8 +232,19 @@ class VerifierDeps { // Returns a string ID of the descriptor of the declaring class of `element`, // or `kUnresolvedMarker` if `element` is null. - template <typename T> - uint32_t GetDeclaringClassStringId(const DexFile& dex_file, T* element) + uint32_t GetMethodDeclaringClassStringId(const DexFile& dex_file, + uint32_t dex_method_idx, + ArtMethod* method) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(Locks::verifier_deps_lock_); + uint32_t GetFieldDeclaringClassStringId(const DexFile& dex_file, + uint32_t dex_field_idx, + ArtField* field) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(Locks::verifier_deps_lock_); + + // Returns a string ID of the descriptor of the class. + uint32_t GetClassDescriptorStringId(const DexFile& dex_file, ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::verifier_deps_lock_); |