diff options
author | 2024-05-06 07:43:35 +0000 | |
---|---|---|
committer | 2024-05-09 09:24:11 +0000 | |
commit | 1ca987e8b5cc2b9b3a15fc8187b987678c54b899 (patch) | |
tree | 27d9c4d9406713d2287e2e9abfbb068198a02d50 /runtime/mirror/class.cc | |
parent | 8e4b50a62ddb7ecfecb3e0caf3cab9f0e35eee76 (diff) |
Avoid some `std::string` construction in `ClassTable`.
Do not construct a `std::string` when compaing most class
descriptors for `Class` objects. We still construct it for
the edge case when comparing a proxy class and non-proxy
class descriptors which should really yield false, except
that ART does not propely enforce the namespace separation.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 338123769
Change-Id: I001abf9dd6648621e86f43a8234d2c0c1d02471c
Diffstat (limited to 'runtime/mirror/class.cc')
-rw-r--r-- | runtime/mirror/class.cc | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 828ab968a3..c69a6721bc 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -1691,6 +1691,68 @@ ObjPtr<Class> Class::CopyOf(Handle<Class> h_this, return new_class->AsClass(); } +bool Class::DescriptorEquals(ObjPtr<mirror::Class> match) { + DCHECK(match != nullptr); + ObjPtr<mirror::Class> klass = this; + while (klass->IsArrayClass()) { + // No read barrier needed, we're reading a chain of constant references for comparison + // with null. Then we follow up below with reading constant references to read constant + // primitive data in both proxy and non-proxy paths. See ReadBarrierOption. + klass = klass->GetComponentType<kDefaultVerifyFlags, kWithoutReadBarrier>(); + DCHECK(klass != nullptr); + match = match->GetComponentType<kDefaultVerifyFlags, kWithoutReadBarrier>(); + if (match == nullptr){ + return false; + } + } + if (match->IsArrayClass()) { + return false; + } + + if (UNLIKELY(klass->IsPrimitive()) || UNLIKELY(match->IsPrimitive())) { + return klass->GetPrimitiveType() == match->GetPrimitiveType(); + } + + if (UNLIKELY(klass->IsProxyClass())) { + return klass->ProxyDescriptorEquals(match); + } + if (UNLIKELY(match->IsProxyClass())) { + return match->ProxyDescriptorEquals(klass); + } + + const DexFile& klass_dex_file = klass->GetDexFile(); + const DexFile& match_dex_file = match->GetDexFile(); + dex::TypeIndex klass_type_index = klass->GetDexTypeIndex(); + dex::TypeIndex match_type_index = match->GetDexTypeIndex(); + if (&klass_dex_file == &match_dex_file) { + return klass_type_index == match_type_index; + } + std::string_view klass_descriptor = klass_dex_file.GetTypeDescriptorView(klass_type_index); + std::string_view match_descriptor = match_dex_file.GetTypeDescriptorView(match_type_index); + return klass_descriptor == match_descriptor; +} + +bool Class::ProxyDescriptorEquals(ObjPtr<mirror::Class> match) { + DCHECK(IsProxyClass()); + ObjPtr<mirror::String> name = GetName<kVerifyNone, kWithoutReadBarrier>(); + DCHECK(name != nullptr); + + DCHECK(match != nullptr); + DCHECK(!match->IsArrayClass()); + DCHECK(!match->IsPrimitive()); + if (match->IsProxyClass()) { + ObjPtr<mirror::String> match_name = match->GetName<kVerifyNone, kWithoutReadBarrier>(); + DCHECK(name != nullptr); + return name->Equals(match_name); + } + + // Note: Proxy descriptor should never match a non-proxy descriptor but ART does not enforce that. + std::string descriptor = DotToDescriptor(name->ToModifiedUtf8().c_str()); + std::string_view match_descriptor = + match->GetDexFile().GetTypeDescriptorView(match->GetDexTypeIndex()); + return descriptor == match_descriptor; +} + bool Class::ProxyDescriptorEquals(const char* match) { DCHECK(IsProxyClass()); std::string storage; |