summaryrefslogtreecommitdiff
path: root/runtime/mirror/class.cc
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-05-06 07:43:35 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-05-09 09:24:11 +0000
commit1ca987e8b5cc2b9b3a15fc8187b987678c54b899 (patch)
tree27d9c4d9406713d2287e2e9abfbb068198a02d50 /runtime/mirror/class.cc
parent8e4b50a62ddb7ecfecb3e0caf3cab9f0e35eee76 (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.cc62
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;