Move ArtField to ObjPtr
Added EXPECT_OBJ_PTR_EQ and variants to gtests.
Fixed moving GC bugs in:
ClassLinker::CreatePathClassLoader
ClassLinkerTest: StaticFields
ObjPtr Decode call sites: 186 -> 181.
Some tests fail due to ResolvedFieldAccessTest, will fix in follow
up CL.
Bug: 31113334
Test: test-art-host CC baker
Change-Id: I8b266ad00f3c20c8cbe7cfdf280d175083df0b88
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 5a5f717..8aebd6e 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -341,13 +341,13 @@
// Don't forget about primitive types.
// Object[] = int[] --> false
//
-inline bool Class::IsArrayAssignableFromArray(Class* src) {
+inline bool Class::IsArrayAssignableFromArray(ObjPtr<Class> src) {
DCHECK(IsArrayClass()) << PrettyClass(this);
DCHECK(src->IsArrayClass()) << PrettyClass(src);
return GetComponentType()->IsAssignableFrom(src->GetComponentType());
}
-inline bool Class::IsAssignableFromArray(Class* src) {
+inline bool Class::IsAssignableFromArray(ObjPtr<Class> src) {
DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom
DCHECK(src->IsArrayClass()) << PrettyClass(src);
if (!IsArrayClass()) {
@@ -362,8 +362,10 @@
}
template <bool throw_on_failure, bool use_referrers_cache>
-inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field,
- uint32_t field_idx, DexCache* dex_cache) {
+inline bool Class::ResolvedFieldAccessTest(Class* access_to,
+ ArtField* field,
+ uint32_t field_idx,
+ DexCache* dex_cache) {
DCHECK_EQ(use_referrers_cache, dex_cache == nullptr);
if (UNLIKELY(!this->CanAccess(access_to))) {
// The referrer class can't access the field's declaring class but may still be able
@@ -447,14 +449,20 @@
return false;
}
-inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field,
- DexCache* dex_cache, uint32_t field_idx) {
- return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, dex_cache);
+inline bool Class::CanAccessResolvedField(ObjPtr<Class> access_to,
+ ArtField* field,
+ ObjPtr<DexCache> dex_cache,
+ uint32_t field_idx) {
+ return ResolvedFieldAccessTest<false, false>(access_to.Decode(),
+ field,
+ field_idx,
+ dex_cache.Decode());
}
-inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field,
+inline bool Class::CheckResolvedFieldAccess(ObjPtr<Class> access_to,
+ ArtField* field,
uint32_t field_idx) {
- return ResolvedFieldAccessTest<true, true>(access_to, field, field_idx, nullptr);
+ return ResolvedFieldAccessTest<true, true>(access_to.Decode(), field, field_idx, nullptr);
}
inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method,
@@ -469,10 +477,10 @@
nullptr);
}
-inline bool Class::IsSubClass(Class* klass) {
+inline bool Class::IsSubClass(ObjPtr<Class> klass) {
DCHECK(!IsInterface()) << PrettyClass(this);
DCHECK(!IsArrayClass()) << PrettyClass(this);
- Class* current = this;
+ ObjPtr<Class> current = this;
do {
if (current == klass) {
return true;
@@ -1032,7 +1040,7 @@
return GetComponentType<kVerifyFlags, kReadBarrierOption>() != nullptr;
}
-inline bool Class::IsAssignableFrom(Class* src) {
+inline bool Class::IsAssignableFrom(ObjPtr<Class> src) {
DCHECK(src != nullptr);
if (this == src) {
// Can always assign to things of the same type.
@@ -1113,6 +1121,34 @@
}
}
+inline bool Class::CanAccess(ObjPtr<Class> that) {
+ return that->IsPublic() || this->IsInSamePackage(that);
+}
+
+
+inline bool Class::CanAccessMember(ObjPtr<Class> access_to, uint32_t member_flags) {
+ // Classes can access all of their own members
+ if (this == access_to) {
+ return true;
+ }
+ // Public members are trivially accessible
+ if (member_flags & kAccPublic) {
+ return true;
+ }
+ // Private members are trivially not accessible
+ if (member_flags & kAccPrivate) {
+ return false;
+ }
+ // Check for protected access from a sub-class, which may or may not be in the same package.
+ if (member_flags & kAccProtected) {
+ if (!this->IsInterface() && this->IsSubClass(access_to)) {
+ return true;
+ }
+ }
+ // Allow protected access from other classes in the same package.
+ return this->IsInSamePackage(access_to);
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 2e5f532..40742d2 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -308,9 +308,9 @@
}
}
-bool Class::IsInSamePackage(Class* that) {
- Class* klass1 = this;
- Class* klass2 = that;
+bool Class::IsInSamePackage(ObjPtr<Class> that) {
+ ObjPtr<Class> klass1 = this;
+ ObjPtr<Class> klass2 = that;
if (klass1 == klass2) {
return true;
}
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 6c1259b..d38f235 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -611,50 +611,28 @@
}
// Returns true if this class is in the same packages as that class.
- bool IsInSamePackage(Class* that) REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsInSamePackage(ObjPtr<Class> that) REQUIRES_SHARED(Locks::mutator_lock_);
static bool IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2);
// Returns true if this class can access that class.
- bool CanAccess(Class* that) REQUIRES_SHARED(Locks::mutator_lock_) {
- return that->IsPublic() || this->IsInSamePackage(that);
- }
+ bool CanAccess(ObjPtr<Class> that) REQUIRES_SHARED(Locks::mutator_lock_);
// Can this class access a member in the provided class with the provided member access flags?
// Note that access to the class isn't checked in case the declaring class is protected and the
// method has been exposed by a public sub-class
- bool CanAccessMember(Class* access_to, uint32_t member_flags)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- // Classes can access all of their own members
- if (this == access_to) {
- return true;
- }
- // Public members are trivially accessible
- if (member_flags & kAccPublic) {
- return true;
- }
- // Private members are trivially not accessible
- if (member_flags & kAccPrivate) {
- return false;
- }
- // Check for protected access from a sub-class, which may or may not be in the same package.
- if (member_flags & kAccProtected) {
- if (!this->IsInterface() && this->IsSubClass(access_to)) {
- return true;
- }
- }
- // Allow protected access from other classes in the same package.
- return this->IsInSamePackage(access_to);
- }
+ bool CanAccessMember(ObjPtr<Class> access_to, uint32_t member_flags)
+ REQUIRES_SHARED(Locks::mutator_lock_);
// Can this class access a resolved field?
// Note that access to field's class is checked and this may require looking up the class
// referenced by the FieldId in the DexFile in case the declaring class is inaccessible.
- bool CanAccessResolvedField(Class* access_to, ArtField* field,
- DexCache* dex_cache, uint32_t field_idx)
+ bool CanAccessResolvedField(ObjPtr<Class> access_to,
+ ArtField* field,
+ ObjPtr<DexCache> dex_cache,
+ uint32_t field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
- bool CheckResolvedFieldAccess(Class* access_to, ArtField* field,
- uint32_t field_idx)
+ bool CheckResolvedFieldAccess(ObjPtr<Class> access_to, ArtField* field, uint32_t field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
// Can this class access a resolved method?
@@ -668,14 +646,14 @@
uint32_t method_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
- bool IsSubClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsSubClass(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
// Can src be assigned to this class? For example, String can be assigned to Object (by an
// upcast), however, an Object cannot be assigned to a String as a potentially exception throwing
// downcast would be necessary. Similarly for interfaces, a class that implements (or an interface
// that extends) another can be assigned to its parent, but not vice-versa. All Classes may assign
// to themselves. Classes for primitive types may not assign to each other.
- ALWAYS_INLINE bool IsAssignableFrom(Class* src) REQUIRES_SHARED(Locks::mutator_lock_);
+ ALWAYS_INLINE bool IsAssignableFrom(ObjPtr<Class> src) REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
@@ -1309,8 +1287,10 @@
void SetVerifyError(Object* klass) REQUIRES_SHARED(Locks::mutator_lock_);
template <bool throw_on_failure, bool use_referrers_cache>
- bool ResolvedFieldAccessTest(Class* access_to, ArtField* field,
- uint32_t field_idx, DexCache* dex_cache)
+ bool ResolvedFieldAccessTest(Class* access_to,
+ ArtField* field,
+ uint32_t field_idx,
+ DexCache* dex_cache)
REQUIRES_SHARED(Locks::mutator_lock_);
template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type>
bool ResolvedMethodAccessTest(Class* access_to, ArtMethod* resolved_method,
@@ -1318,8 +1298,8 @@
REQUIRES_SHARED(Locks::mutator_lock_);
bool Implements(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- bool IsArrayAssignableFromArray(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- bool IsAssignableFromArray(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsArrayAssignableFromArray(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsAssignableFromArray(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
void CheckObjectAlloc() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 8b0f8ce..ec32cb6 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -78,6 +78,11 @@
return ret.Get();
}
+template<bool kTransactionActive>
+void Field::SetDeclaringClass(ObjPtr<mirror::Class> c) {
+ SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c.Decode());
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index f378568..c5357c9 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -20,6 +20,7 @@
#include "accessible_object.h"
#include "base/enums.h"
#include "gc_root.h"
+#include "obj_ptr.h"
#include "object.h"
#include "object_callbacks.h"
#include "read_barrier_option.h"
@@ -109,9 +110,7 @@
int32_t offset_;
template<bool kTransactionActive>
- void SetDeclaringClass(mirror::Class* c) REQUIRES_SHARED(Locks::mutator_lock_) {
- SetFieldObject<kTransactionActive>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c);
- }
+ void SetDeclaringClass(ObjPtr<mirror::Class> c) REQUIRES_SHARED(Locks::mutator_lock_);
template<bool kTransactionActive>
void SetType(mirror::Class* type) REQUIRES_SHARED(Locks::mutator_lock_) {
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index c37deb5..90b97fd 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -213,7 +213,7 @@
if (field.GetOffset().Int32Value() == field_offset.Int32Value()) {
CHECK_NE(field.GetTypeAsPrimitiveType(), Primitive::kPrimNot);
// TODO: resolve the field type for moving GC.
- mirror::Class* field_type = field.GetType<!kMovingCollector>();
+ ObjPtr<mirror::Class> field_type = field.GetType<!kMovingCollector>();
if (field_type != nullptr) {
CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
}
@@ -230,7 +230,7 @@
if (field.GetOffset().Int32Value() == field_offset.Int32Value()) {
CHECK_NE(field.GetTypeAsPrimitiveType(), Primitive::kPrimNot);
// TODO: resolve the field type for moving GC.
- mirror::Class* field_type = field.GetType<!kMovingCollector>();
+ ObjPtr<mirror::Class> field_type = field.GetType<!kMovingCollector>();
if (field_type != nullptr) {
CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
}
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 40ee3a2..a573ae6 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -384,12 +384,12 @@
ArtField* field = FindFieldFromCode<StaticObjectRead, true>(field_idx, clinit, Thread::Current(),
sizeof(HeapReference<Object>));
- Object* s0 = field->GetObj(klass);
+ ObjPtr<Object> s0 = field->GetObj(klass);
EXPECT_TRUE(s0 != nullptr);
Handle<CharArray> char_array(hs.NewHandle(CharArray::Alloc(soa.Self(), 0)));
field->SetObj<false>(field->GetDeclaringClass(), char_array.Get());
- EXPECT_EQ(char_array.Get(), field->GetObj(klass));
+ EXPECT_OBJ_PTR_EQ(char_array.Get(), field->GetObj(klass));
field->SetObj<false>(field->GetDeclaringClass(), nullptr);
EXPECT_EQ(nullptr, field->GetObj(klass));
@@ -759,7 +759,7 @@
EXPECT_TRUE(!X.IsNull());
EXPECT_TRUE(X.IsValid());
EXPECT_TRUE(X.Decode() != nullptr);
- EXPECT_EQ(h_X.Get(), X.Decode());
+ EXPECT_OBJ_PTR_EQ(h_X.Get(), X);
// FindClass may cause thread suspension, it should invalidate X.
ObjPtr<Class, /*kPoison*/ true> Y(class_linker_->FindClass(soa.Self(), "LY;", class_loader));
EXPECT_TRUE(!Y.IsNull());
@@ -773,7 +773,7 @@
X.Assign(h_X.Get());
EXPECT_TRUE(!X.IsNull());
EXPECT_TRUE(X.IsValid());
- EXPECT_EQ(h_X.Get(), X.Decode());
+ EXPECT_OBJ_PTR_EQ(h_X.Get(), X);
// Allow thread suspension to invalidate Y.
soa.Self()->AllowThreadSuspension();
@@ -793,7 +793,7 @@
unpoisoned = h_X.Get();
EXPECT_FALSE(unpoisoned.IsNull());
EXPECT_TRUE(unpoisoned == h_X.Get());
- EXPECT_EQ(unpoisoned.Decode(), h_X.Get());
+ EXPECT_OBJ_PTR_EQ(unpoisoned, h_X.Get());
}
} // namespace mirror