Clean up Class::GetDirectInterface().
Once the `klass` has been resolved, this function should not
need to resolve interface types anymore. Drop the type
resolution from this function and pass the Class as ObjPtr<>
instead of Handle<>. Make callers that expect non-null
result DCHECK() that assumption. For the callers that may
actually need to resolve these interface classes, introduce
a new function ResolveDirectInterface().
Also improve ObjPtr<> constructors and assignment operator
to improve overload resolution. For example, if we have
foo(ObjPtr<T1>) and foo(ObjPtr<T2>), calling foo(.) with
a T1* would have previously been ambiguous even if T1 is
not a base of T2.
Test: m test-art-host
Change-Id: Iff44a7285f68f0af4507fc9ba37343865422fe84
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 0cfe29b..a862c97 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -276,7 +276,7 @@
if (num_direct_interfaces > 0) {
os << " interfaces (" << num_direct_interfaces << "):\n";
for (size_t i = 0; i < num_direct_interfaces; ++i) {
- ObjPtr<Class> interface = GetDirectInterface(self, h_this, i);
+ ObjPtr<Class> interface = GetDirectInterface(self, h_this.Get(), i);
if (interface == nullptr) {
os << StringPrintf(" %2zd: nullptr!\n", i);
} else {
@@ -799,24 +799,21 @@
}
ArtField* Class::FindStaticField(Thread* self,
- Handle<Class> klass,
+ ObjPtr<Class> klass,
const StringPiece& name,
const StringPiece& type) {
// Is the field in this class (or its interfaces), or any of its
// superclasses (or their interfaces)?
- for (ObjPtr<Class> k = klass.Get(); k != nullptr; k = k->GetSuperClass()) {
+ for (ObjPtr<Class> k = klass; k != nullptr; k = k->GetSuperClass()) {
// Is the field in this class?
ArtField* f = k->FindDeclaredStaticField(name, type);
if (f != nullptr) {
return f;
}
- // Wrap k incase it moves during GetDirectInterface.
- StackHandleScope<1> hs(self);
- HandleWrapperObjPtr<Class> h_k(hs.NewHandleWrapper(&k));
// Is this field in any of this class' interfaces?
- for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
- StackHandleScope<1> hs2(self);
- Handle<Class> interface(hs2.NewHandle(GetDirectInterface(self, h_k, i)));
+ for (uint32_t i = 0, num_interfaces = k->NumDirectInterfaces(); i != num_interfaces; ++i) {
+ ObjPtr<Class> interface = GetDirectInterface(self, k, i);
+ DCHECK(interface != nullptr);
f = FindStaticField(self, interface, name, type);
if (f != nullptr) {
return f;
@@ -839,11 +836,10 @@
// Though GetDirectInterface() should not cause thread suspension when called
// from here, it takes a Handle as an argument, so we need to wrap `k`.
ScopedAssertNoThreadSuspension ants(__FUNCTION__);
- StackHandleScope<1> hs(self);
- Handle<Class> h_k(hs.NewHandle(k));
// Is this field in any of this class' interfaces?
- for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
- ObjPtr<Class> interface = GetDirectInterface(self, h_k, i);
+ for (uint32_t i = 0, num_interfaces = k->NumDirectInterfaces(); i != num_interfaces; ++i) {
+ ObjPtr<Class> interface = GetDirectInterface(self, k, i);
+ DCHECK(interface != nullptr);
f = FindStaticField(self, interface, dex_cache, dex_field_idx);
if (f != nullptr) {
return f;
@@ -854,11 +850,11 @@
}
ArtField* Class::FindField(Thread* self,
- Handle<Class> klass,
+ ObjPtr<Class> klass,
const StringPiece& name,
const StringPiece& type) {
// Find a field using the JLS field resolution order
- for (ObjPtr<Class> k = klass.Get(); k != nullptr; k = k->GetSuperClass()) {
+ for (ObjPtr<Class> k = klass; k != nullptr; k = k->GetSuperClass()) {
// Is the field in this class?
ArtField* f = k->FindDeclaredInstanceField(name, type);
if (f != nullptr) {
@@ -869,12 +865,10 @@
return f;
}
// Is this field in any of this class' interfaces?
- StackHandleScope<1> hs(self);
- HandleWrapperObjPtr<Class> h_k(hs.NewHandleWrapper(&k));
- for (uint32_t i = 0; i < h_k->NumDirectInterfaces(); ++i) {
- StackHandleScope<1> hs2(self);
- Handle<Class> interface(hs2.NewHandle(GetDirectInterface(self, h_k, i)));
- f = interface->FindStaticField(self, interface, name, type);
+ for (uint32_t i = 0, num_interfaces = k->NumDirectInterfaces(); i != num_interfaces; ++i) {
+ ObjPtr<Class> interface = GetDirectInterface(self, k, i);
+ DCHECK(interface != nullptr);
+ f = FindStaticField(self, interface, name, type);
if (f != nullptr) {
return f;
}
@@ -929,36 +923,46 @@
return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
}
-ObjPtr<Class> Class::GetDirectInterface(Thread* self,
- Handle<Class> klass,
- uint32_t idx) {
- DCHECK(klass.Get() != nullptr);
+ObjPtr<Class> Class::GetDirectInterface(Thread* self, ObjPtr<Class> klass, uint32_t idx) {
+ DCHECK(klass != nullptr);
DCHECK(!klass->IsPrimitive());
if (klass->IsArrayClass()) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ // Use ClassLinker::LookupClass(); avoid poisoning ObjPtr<>s by ClassLinker::FindSystemClass().
+ ObjPtr<Class> interface;
if (idx == 0) {
- return class_linker->FindSystemClass(self, "Ljava/lang/Cloneable;");
+ interface = class_linker->LookupClass(self, "Ljava/lang/Cloneable;", nullptr);
} else {
DCHECK_EQ(1U, idx);
- return class_linker->FindSystemClass(self, "Ljava/io/Serializable;");
+ interface = class_linker->LookupClass(self, "Ljava/io/Serializable;", nullptr);
}
+ DCHECK(interface != nullptr);
+ return interface;
} else if (klass->IsProxyClass()) {
- ObjPtr<ObjectArray<Class>> interfaces = klass.Get()->GetInterfaces();
+ ObjPtr<ObjectArray<Class>> interfaces = klass->GetInterfaces();
DCHECK(interfaces != nullptr);
return interfaces->Get(idx);
} else {
dex::TypeIndex type_idx = klass->GetDirectInterfaceTypeIdx(idx);
ObjPtr<Class> interface = klass->GetDexCache()->GetResolvedType(type_idx);
- if (interface == nullptr) {
- interface = Runtime::Current()->GetClassLinker()->ResolveType(klass->GetDexFile(),
- type_idx,
- klass.Get());
- CHECK(interface != nullptr || self->IsExceptionPending());
- }
return interface;
}
}
+ObjPtr<Class> Class::ResolveDirectInterface(Thread* self, Handle<Class> klass, uint32_t idx) {
+ ObjPtr<Class> interface = GetDirectInterface(self, klass.Get(), idx);
+ if (interface == nullptr) {
+ DCHECK(!klass->IsArrayClass());
+ DCHECK(!klass->IsProxyClass());
+ dex::TypeIndex type_idx = klass->GetDirectInterfaceTypeIdx(idx);
+ interface = Runtime::Current()->GetClassLinker()->ResolveType(klass->GetDexFile(),
+ type_idx,
+ klass.Get());
+ CHECK(interface != nullptr || self->IsExceptionPending());
+ }
+ return interface;
+}
+
ObjPtr<Class> Class::GetCommonSuperClass(Handle<Class> klass) {
DCHECK(klass.Get() != nullptr);
DCHECK(!klass->IsInterface());
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 248c941..d7449c8 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1087,7 +1087,9 @@
ArtField* GetStaticField(uint32_t i) REQUIRES_SHARED(Locks::mutator_lock_);
// Find a static or instance field using the JLS resolution order
- static ArtField* FindField(Thread* self, Handle<Class> klass, const StringPiece& name,
+ static ArtField* FindField(Thread* self,
+ ObjPtr<Class> klass,
+ const StringPiece& name,
const StringPiece& type)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1108,7 +1110,7 @@
// Finds the given static field in this class or a superclass.
static ArtField* FindStaticField(Thread* self,
- Handle<Class> klass,
+ ObjPtr<Class> klass,
const StringPiece& name,
const StringPiece& type)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -1204,9 +1206,15 @@
dex::TypeIndex GetDirectInterfaceTypeIdx(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_);
- static ObjPtr<Class> GetDirectInterface(Thread* self,
- Handle<Class> klass,
- uint32_t idx)
+ // Get the direct interface of the `klass` at index `idx` if resolved, otherwise return null.
+ // If the caller expects the interface to be resolved, for example for a resolved `klass`,
+ // that assumption should be checked by `DCHECK(result != nullptr)`.
+ static ObjPtr<Class> GetDirectInterface(Thread* self, ObjPtr<Class> klass, uint32_t idx)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ // Resolve and get the direct interface of the `klass` at index `idx`.
+ // Returns null with a pending exception if the resolution fails.
+ static ObjPtr<Class> ResolveDirectInterface(Thread* self, Handle<Class> klass, uint32_t idx)
REQUIRES_SHARED(Locks::mutator_lock_);
const char* GetSourceFile() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 4b47f7f..a6f56ae 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -140,9 +140,9 @@
Handle<mirror::Class> klass(hs.NewHandle(oa->GetClass()));
ASSERT_EQ(2U, klass->NumDirectInterfaces());
EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;"),
- mirror::Class::GetDirectInterface(soa.Self(), klass, 0));
+ mirror::Class::GetDirectInterface(soa.Self(), klass.Get(), 0));
EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;"),
- mirror::Class::GetDirectInterface(soa.Self(), klass, 1));
+ mirror::Class::GetDirectInterface(soa.Self(), klass.Get(), 1));
}
TEST_F(ObjectTest, AllocArray) {
@@ -708,19 +708,19 @@
// Wrong type.
EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "I") == nullptr);
EXPECT_TRUE(mirror::Class::FindStaticField(
- soa.Self(), c, "CASE_INSENSITIVE_ORDER", "I") == nullptr);
+ soa.Self(), c.Get(), "CASE_INSENSITIVE_ORDER", "I") == nullptr);
// Wrong name.
EXPECT_TRUE(c->FindDeclaredStaticField(
"cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == nullptr);
EXPECT_TRUE(
- mirror::Class::FindStaticField(soa.Self(), c, "cASE_INSENSITIVE_ORDER",
- "Ljava/util/Comparator;") == nullptr);
+ mirror::Class::FindStaticField(
+ soa.Self(), c.Get(), "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == nullptr);
// Right name and type.
ArtField* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- ArtField* f2 = mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER",
- "Ljava/util/Comparator;");
+ ArtField* f2 = mirror::Class::FindStaticField(
+ soa.Self(), c.Get(), "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
EXPECT_TRUE(f1 != nullptr);
EXPECT_TRUE(f2 != nullptr);
EXPECT_EQ(f1, f2);