From: Mathieu Chartier Date: Fri, 30 Sep 2016 17:27:43 +0000 (-0700) Subject: Move ArtField to ObjPtr X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=3398c7874e002beaa6c2b2fadf183e7d1ddad23a;p=android-x86%2Fart.git 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/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index 2d0dd3cda..b4730cc05 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -103,7 +103,7 @@ inline ArtField* CompilerDriver::ResolveField( inline void CompilerDriver::GetResolvedFieldDexFileLocation( ArtField* resolved_field, const DexFile** declaring_dex_file, uint16_t* declaring_class_idx, uint16_t* declaring_field_idx) { - mirror::Class* declaring_class = resolved_field->GetDeclaringClass(); + ObjPtr declaring_class = resolved_field->GetDeclaringClass(); *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile(); *declaring_class_idx = declaring_class->GetDexTypeIndex(); *declaring_field_idx = resolved_field->GetDexFieldIndex(); @@ -121,10 +121,12 @@ inline std::pair CompilerDriver::IsFastInstanceField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, ArtField* resolved_field, uint16_t field_idx) { DCHECK(!resolved_field->IsStatic()); - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + ObjPtr fields_class = resolved_field->GetDeclaringClass(); bool fast_get = referrer_class != nullptr && - referrer_class->CanAccessResolvedField(fields_class, resolved_field, - dex_cache, field_idx); + referrer_class->CanAccessResolvedField(fields_class.Decode(), + resolved_field, + dex_cache, + field_idx); bool fast_put = fast_get && (!resolved_field->IsFinal() || fields_class == referrer_class); return std::make_pair(fast_get, fast_put); } @@ -167,13 +169,13 @@ inline std::pair CompilerDriver::IsClassOfStaticMemberAvailableToRef uint32_t* storage_index) { DCHECK(resolved_member->IsStatic()); if (LIKELY(referrer_class != nullptr)) { - mirror::Class* members_class = resolved_member->GetDeclaringClass(); + ObjPtr members_class = resolved_member->GetDeclaringClass(); if (members_class == referrer_class) { *storage_index = members_class->GetDexTypeIndex(); return std::make_pair(true, true); } if (CanAccessResolvedMember( - referrer_class, members_class, resolved_member, dex_cache, member_idx)) { + referrer_class, members_class.Decode(), resolved_member, dex_cache, member_idx)) { // We have the resolved member, we must make it into a index for the referrer // in its static storage (which may fail if it doesn't have a slot for it) // TODO: for images we can elide the static storage base null check @@ -220,7 +222,7 @@ inline bool CompilerDriver::IsClassOfStaticMethodAvailableToReferrer( inline bool CompilerDriver::IsStaticFieldInReferrerClass(mirror::Class* referrer_class, ArtField* resolved_field) { DCHECK(resolved_field->IsStatic()); - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + ObjPtr fields_class = resolved_field->GetDeclaringClass(); return referrer_class == fields_class; } @@ -250,8 +252,8 @@ inline bool CompilerDriver::CanReferrerAssumeClassIsInitialized(mirror::Class* r inline bool CompilerDriver::IsStaticFieldsClassInitialized(mirror::Class* referrer_class, ArtField* resolved_field) { DCHECK(resolved_field->IsStatic()); - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); - return CanReferrerAssumeClassIsInitialized(referrer_class, fields_class); + ObjPtr fields_class = resolved_field->GetDeclaringClass(); + return CanReferrerAssumeClassIsInitialized(referrer_class, fields_class.Decode()); } inline ArtMethod* CompilerDriver::ResolveMethod( diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 41bda60a6..210943c88 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -908,7 +908,7 @@ void ImageWriter::PruneNonImageClasses() { ArtField** resolved_fields = dex_cache->GetResolvedFields(); for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { ArtField* field = mirror::DexCache::GetElementPtrSize(resolved_fields, i, target_ptr_size_); - if (field != nullptr && !KeepClass(field->GetDeclaringClass())) { + if (field != nullptr && !KeepClass(field->GetDeclaringClass().Decode())) { dex_cache->SetResolvedField(i, nullptr, target_ptr_size_); } } @@ -1742,7 +1742,7 @@ void ImageWriter::CopyAndFixupNativeData(size_t oat_index) { case kNativeObjectRelocationTypeArtField: { memcpy(dest, pair.first, sizeof(ArtField)); reinterpret_cast(dest)->SetDeclaringClass( - GetImageAddress(reinterpret_cast(pair.first)->GetDeclaringClass())); + GetImageAddress(reinterpret_cast(pair.first)->GetDeclaringClass().Decode())); break; } case kNativeObjectRelocationTypeRuntimeMethod: diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 5a47df1a0..15cebfe71 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -84,7 +84,7 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { void VisitNewArray(HNewArray* instr) OVERRIDE; void VisitParameterValue(HParameterValue* instr) OVERRIDE; void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info); - void SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass, bool is_exact) + void SetClassAsTypeInfo(HInstruction* instr, ObjPtr klass, bool is_exact) REQUIRES_SHARED(Locks::mutator_lock_); void VisitInstanceFieldGet(HInstanceFieldGet* instr) OVERRIDE; void VisitStaticFieldGet(HStaticFieldGet* instr) OVERRIDE; @@ -427,7 +427,7 @@ void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) { } void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* instr, - mirror::Class* klass, + ObjPtr klass, bool is_exact) { if (instr->IsInvokeStaticOrDirect() && instr->AsInvokeStaticOrDirect()->IsStringInit()) { // Calls to String. are replaced with a StringFactory. @@ -454,7 +454,7 @@ void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* inst } instr->SetReferenceTypeInfo( ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true)); - } else if (IsAdmissible(klass)) { + } else if (IsAdmissible(klass.Decode())) { ReferenceTypeInfo::TypeHandle handle = handle_cache_->NewHandle(klass); is_exact = is_exact || handle->CannotBeAssignedFromOtherTypes(); instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact)); @@ -512,7 +512,7 @@ void ReferenceTypePropagation::RTPVisitor::UpdateFieldAccessTypeInfo(HInstructio } ScopedObjectAccess soa(Thread::Current()); - mirror::Class* klass = nullptr; + ObjPtr klass; // The field index is unknown only during tests. if (info.GetFieldIndex() != kUnknownFieldIndex) { diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h index 1fa662490..61428b2a4 100644 --- a/compiler/optimizing/reference_type_propagation.h +++ b/compiler/optimizing/reference_type_propagation.h @@ -21,6 +21,7 @@ #include "driver/dex_compilation_unit.h" #include "handle_scope-inl.h" #include "nodes.h" +#include "obj_ptr.h" #include "optimization.h" #include "optimizing_compiler_stats.h" @@ -62,6 +63,11 @@ class ReferenceTypePropagation : public HOptimization { return handles_->NewHandle(object); } + template + MutableHandle NewHandle(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_) { + return handles_->NewHandle(object); + } + ReferenceTypeInfo::TypeHandle GetObjectClassHandle(); ReferenceTypeInfo::TypeHandle GetClassClassHandle(); ReferenceTypeInfo::TypeHandle GetStringClassHandle(); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index be5224beb..4d0dc5696 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -1687,7 +1687,9 @@ class ImageDumper { ImageDumper* const image_dumper_; }; - static void PrettyObjectValue(std::ostream& os, mirror::Class* type, mirror::Object* value) + static void PrettyObjectValue(std::ostream& os, + ObjPtr type, + ObjPtr value) REQUIRES_SHARED(Locks::mutator_lock_) { CHECK(type != nullptr); if (value == nullptr) { @@ -1700,11 +1702,11 @@ class ImageDumper { mirror::Class* klass = value->AsClass(); os << StringPrintf("%p Class: %s\n", klass, PrettyDescriptor(klass).c_str()); } else { - os << StringPrintf("%p %s\n", value, PrettyDescriptor(type).c_str()); + os << StringPrintf("%p %s\n", value.Decode(), PrettyDescriptor(type).c_str()); } } - static void PrintField(std::ostream& os, ArtField* field, mirror::Object* obj) + static void PrintField(std::ostream& os, ArtField* field, ObjPtr obj) REQUIRES_SHARED(Locks::mutator_lock_) { os << StringPrintf("%s: ", field->GetName()); switch (field->GetTypeAsPrimitiveType()) { @@ -1736,16 +1738,17 @@ class ImageDumper { case Primitive::kPrimNot: { // Get the value, don't compute the type unless it is non-null as we don't want // to cause class loading. - mirror::Object* value = field->GetObj(obj); + ObjPtr value = field->GetObj(obj); if (value == nullptr) { os << StringPrintf("null %s\n", PrettyDescriptor(field->GetTypeDescriptor()).c_str()); } else { // Grab the field type without causing resolution. - mirror::Class* field_type = field->GetType(); + ObjPtr field_type = field->GetType(); if (field_type != nullptr) { PrettyObjectValue(os, field_type, value); } else { - os << StringPrintf("%p %s\n", value, + os << StringPrintf("%p %s\n", + value.Decode(), PrettyDescriptor(field->GetTypeDescriptor()).c_str()); } } diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index d58f38cc0..b259f64d1 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -504,7 +504,8 @@ class PatchOatArtFieldVisitor : public ArtFieldVisitor { void Visit(ArtField* field) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { ArtField* const dest = patch_oat_->RelocatedCopyOf(field); - dest->SetDeclaringClass(patch_oat_->RelocatedAddressOfPointer(field->GetDeclaringClass())); + dest->SetDeclaringClass( + patch_oat_->RelocatedAddressOfPointer(field->GetDeclaringClass().Decode())); } private: diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc index 5e39f4281..432ba3658 100644 --- a/runtime/arch/stub_test.cc +++ b/runtime/arch/stub_test.cc @@ -1688,7 +1688,7 @@ static void set_and_check_instance(ArtField* f, mirror::Object* trg, EXPECT_EQ(res, reinterpret_cast(val)) << "Value " << val; - EXPECT_EQ(val, f->GetObj(trg)); + EXPECT_OBJ_PTR_EQ(val, f->GetObj(trg)); } #endif diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h index ca9616997..a52c71468 100644 --- a/runtime/art_field-inl.h +++ b/runtime/art_field-inl.h @@ -34,15 +34,15 @@ namespace art { template -inline mirror::Class* ArtField::GetDeclaringClass() { +inline ObjPtr ArtField::GetDeclaringClass() { GcRootSource gc_root_source(this); - mirror::Class* result = declaring_class_.Read(&gc_root_source); + ObjPtr result = declaring_class_.Read(&gc_root_source); DCHECK(result != nullptr); DCHECK(result->IsLoaded() || result->IsErroneous()) << result->GetStatus(); return result; } -inline void ArtField::SetDeclaringClass(mirror::Class* new_declaring_class) { +inline void ArtField::SetDeclaringClass(ObjPtr new_declaring_class) { declaring_class_ = GcRoot(new_declaring_class); } @@ -61,7 +61,7 @@ inline MemberOffset ArtField::GetOffsetDuringLinking() { return MemberOffset(offset_); } -inline uint32_t ArtField::Get32(mirror::Object* object) { +inline uint32_t ArtField::Get32(ObjPtr object) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -71,7 +71,7 @@ inline uint32_t ArtField::Get32(mirror::Object* object) { } template -inline void ArtField::Set32(mirror::Object* object, uint32_t new_value) { +inline void ArtField::Set32(ObjPtr object, uint32_t new_value) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -81,7 +81,7 @@ inline void ArtField::Set32(mirror::Object* object, uint32_t new_value) { } } -inline uint64_t ArtField::Get64(mirror::Object* object) { +inline uint64_t ArtField::Get64(ObjPtr object) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -91,7 +91,7 @@ inline uint64_t ArtField::Get64(mirror::Object* object) { } template -inline void ArtField::Set64(mirror::Object* object, uint64_t new_value) { +inline void ArtField::Set64(ObjPtr object, uint64_t new_value) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -101,23 +101,24 @@ inline void ArtField::Set64(mirror::Object* object, uint64_t new_value) { } } -inline mirror::Object* ArtField::GetObj(mirror::Object* object) { +template +inline ObjPtr ArtField::GetObj(ObjPtr object) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { - return object->GetFieldObjectVolatile(GetOffset()); + return object->GetFieldObjectVolatile(GetOffset()); } - return object->GetFieldObject(GetOffset()); + return object->GetFieldObject(GetOffset()); } template -inline void ArtField::SetObj(mirror::Object* object, mirror::Object* new_value) { +inline void ArtField::SetObj(ObjPtr object, ObjPtr new_value) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { - object->SetFieldObjectVolatile(GetOffset(), new_value); + object->SetFieldObjectVolatile(GetOffset(), new_value.Decode()); } else { - object->SetFieldObject(GetOffset(), new_value); + object->SetFieldObject(GetOffset(), new_value.Decode()); } } @@ -140,46 +141,46 @@ inline void ArtField::SetObj(mirror::Object* object, mirror::Object* new_value) (object)->SetField ## type(GetOffset(), value); \ } -inline uint8_t ArtField::GetBoolean(mirror::Object* object) { +inline uint8_t ArtField::GetBoolean(ObjPtr object) { FIELD_GET(object, Boolean); } template -inline void ArtField::SetBoolean(mirror::Object* object, uint8_t z) { +inline void ArtField::SetBoolean(ObjPtr object, uint8_t z) { FIELD_SET(object, Boolean, z); } -inline int8_t ArtField::GetByte(mirror::Object* object) { +inline int8_t ArtField::GetByte(ObjPtr object) { FIELD_GET(object, Byte); } template -inline void ArtField::SetByte(mirror::Object* object, int8_t b) { +inline void ArtField::SetByte(ObjPtr object, int8_t b) { FIELD_SET(object, Byte, b); } -inline uint16_t ArtField::GetChar(mirror::Object* object) { +inline uint16_t ArtField::GetChar(ObjPtr object) { FIELD_GET(object, Char); } template -inline void ArtField::SetChar(mirror::Object* object, uint16_t c) { +inline void ArtField::SetChar(ObjPtr object, uint16_t c) { FIELD_SET(object, Char, c); } -inline int16_t ArtField::GetShort(mirror::Object* object) { +inline int16_t ArtField::GetShort(ObjPtr object) { FIELD_GET(object, Short); } template -inline void ArtField::SetShort(mirror::Object* object, int16_t s) { +inline void ArtField::SetShort(ObjPtr object, int16_t s) { FIELD_SET(object, Short, s); } #undef FIELD_GET #undef FIELD_SET -inline int32_t ArtField::GetInt(mirror::Object* object) { +inline int32_t ArtField::GetInt(ObjPtr object) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); @@ -188,7 +189,7 @@ inline int32_t ArtField::GetInt(mirror::Object* object) { } template -inline void ArtField::SetInt(mirror::Object* object, int32_t i) { +inline void ArtField::SetInt(ObjPtr object, int32_t i) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); @@ -196,7 +197,7 @@ inline void ArtField::SetInt(mirror::Object* object, int32_t i) { Set32(object, i); } -inline int64_t ArtField::GetLong(mirror::Object* object) { +inline int64_t ArtField::GetLong(ObjPtr object) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); @@ -205,7 +206,7 @@ inline int64_t ArtField::GetLong(mirror::Object* object) { } template -inline void ArtField::SetLong(mirror::Object* object, int64_t j) { +inline void ArtField::SetLong(ObjPtr object, int64_t j) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); @@ -213,7 +214,7 @@ inline void ArtField::SetLong(mirror::Object* object, int64_t j) { Set64(object, j); } -inline float ArtField::GetFloat(mirror::Object* object) { +inline float ArtField::GetFloat(ObjPtr object) { DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetI(Get32(object)); @@ -221,14 +222,14 @@ inline float ArtField::GetFloat(mirror::Object* object) { } template -inline void ArtField::SetFloat(mirror::Object* object, float f) { +inline void ArtField::SetFloat(ObjPtr object, float f) { DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetF(f); Set32(object, bits.GetI()); } -inline double ArtField::GetDouble(mirror::Object* object) { +inline double ArtField::GetDouble(ObjPtr object) { DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetJ(Get64(object)); @@ -236,20 +237,20 @@ inline double ArtField::GetDouble(mirror::Object* object) { } template -inline void ArtField::SetDouble(mirror::Object* object, double d) { +inline void ArtField::SetDouble(ObjPtr object, double d) { DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetD(d); Set64(object, bits.GetJ()); } -inline mirror::Object* ArtField::GetObject(mirror::Object* object) { +inline ObjPtr ArtField::GetObject(ObjPtr object) { DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); return GetObj(object); } template -inline void ArtField::SetObject(mirror::Object* object, mirror::Object* l) { +inline void ArtField::SetObject(ObjPtr object, ObjPtr l) { DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); SetObj(object, l); } @@ -288,16 +289,16 @@ inline bool ArtField::IsPrimitiveType() REQUIRES_SHARED(Locks::mutator_lock_) { } template -inline mirror::Class* ArtField::GetType() { +inline ObjPtr ArtField::GetType() { const uint32_t field_index = GetDexFieldIndex(); - auto* declaring_class = GetDeclaringClass(); + ObjPtr declaring_class = GetDeclaringClass(); if (UNLIKELY(declaring_class->IsProxyClass())) { return ProxyFindSystemClass(GetTypeDescriptor()); } auto* dex_cache = declaring_class->GetDexCache(); const DexFile* const dex_file = dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index); - mirror::Class* type = dex_cache->GetResolvedType(field_id.type_idx_); + ObjPtr type = dex_cache->GetResolvedType(field_id.type_idx_); if (kResolve && UNLIKELY(type == nullptr)) { type = ResolveGetType(field_id.type_idx_); CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); @@ -309,7 +310,7 @@ inline size_t ArtField::FieldSize() REQUIRES_SHARED(Locks::mutator_lock_) { return Primitive::ComponentSize(GetTypeAsPrimitiveType()); } -inline mirror::DexCache* ArtField::GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_) { +inline ObjPtr ArtField::GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_) { return GetDeclaringClass()->GetDexCache(); } @@ -317,13 +318,13 @@ inline const DexFile* ArtField::GetDexFile() REQUIRES_SHARED(Locks::mutator_lock return GetDexCache()->GetDexFile(); } -inline mirror::String* ArtField::GetStringName(Thread* self, bool resolve) { +inline ObjPtr ArtField::GetStringName(Thread* self, bool resolve) { auto dex_field_index = GetDexFieldIndex(); CHECK_NE(dex_field_index, DexFile::kDexNoIndex); - auto* dex_cache = GetDexCache(); + ObjPtr dex_cache = GetDexCache(); const auto* dex_file = dex_cache->GetDexFile(); const auto& field_id = dex_file->GetFieldId(dex_field_index); - auto* name = dex_cache->GetResolvedString(field_id.name_idx_); + ObjPtr name = dex_cache->GetResolvedString(field_id.name_idx_); if (resolve && name == nullptr) { name = ResolveGetStringName(self, *dex_file, field_id.name_idx_, dex_cache); } @@ -337,8 +338,8 @@ inline void ArtField::VisitRoots(RootVisitorType& visitor) { template inline void ArtField::UpdateObjects(const Visitor& visitor) { - mirror::Class* old_class = DeclaringClassRoot().Read(); - mirror::Class* new_class = visitor(old_class); + ObjPtr old_class = DeclaringClassRoot().Read(); + ObjPtr new_class = visitor(old_class.Decode()); if (old_class != new_class) { SetDeclaringClass(new_class); } @@ -369,7 +370,7 @@ static inline ArtField* FindFieldWithOffset( } template -inline ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, +inline ArtField* ArtField::FindInstanceFieldWithOffset(ObjPtr klass, uint32_t field_offset) { DCHECK(klass != nullptr); ArtField* field = FindFieldWithOffset(klass->GetIFields(), field_offset); @@ -382,7 +383,8 @@ inline ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, } template -inline ArtField* ArtField::FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) { +inline ArtField* ArtField::FindStaticFieldWithOffset(ObjPtr klass, + uint32_t field_offset) { DCHECK(klass != nullptr); return FindFieldWithOffset(klass->GetSFields(), field_offset); } diff --git a/runtime/art_field.cc b/runtime/art_field.cc index 3b4db0bd1..78c62d6f3 100644 --- a/runtime/art_field.cc +++ b/runtime/art_field.cc @@ -30,10 +30,6 @@ namespace art { -ArtField::ArtField() : access_flags_(0), field_dex_idx_(0), offset_(0) { - declaring_class_ = GcRoot(nullptr); -} - void ArtField::SetOffset(MemberOffset num_bytes) { DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); if (kIsDebugBuild && Runtime::Current()->IsAotCompiler() && @@ -47,20 +43,23 @@ void ArtField::SetOffset(MemberOffset num_bytes) { offset_ = num_bytes.Uint32Value(); } -mirror::Class* ArtField::ProxyFindSystemClass(const char* descriptor) { +ObjPtr ArtField::ProxyFindSystemClass(const char* descriptor) { DCHECK(GetDeclaringClass()->IsProxyClass()); return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), descriptor); } -mirror::Class* ArtField::ResolveGetType(uint32_t type_idx) { +ObjPtr ArtField::ResolveGetType(uint32_t type_idx) { return Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this); } -mirror::String* ArtField::ResolveGetStringName(Thread* self, const DexFile& dex_file, - uint32_t string_idx, mirror::DexCache* dex_cache) { +ObjPtr ArtField::ResolveGetStringName(Thread* self, + const DexFile& dex_file, + uint32_t string_idx, + ObjPtr dex_cache) { StackHandleScope<1> hs(self); - return Runtime::Current()->GetClassLinker()->ResolveString( - dex_file, string_idx, hs.NewHandle(dex_cache)); + return Runtime::Current()->GetClassLinker()->ResolveString(dex_file, + string_idx, + hs.NewHandle(dex_cache)); } } // namespace art diff --git a/runtime/art_field.h b/runtime/art_field.h index 16e6c758e..8ba383c00 100644 --- a/runtime/art_field.h +++ b/runtime/art_field.h @@ -21,6 +21,7 @@ #include "gc_root.h" #include "modifiers.h" +#include "obj_ptr.h" #include "offsets.h" #include "primitive.h" #include "read_barrier_option.h" @@ -39,12 +40,10 @@ class String; class ArtField FINAL { public: - ArtField(); - template - mirror::Class* GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_); - void SetDeclaringClass(mirror::Class *new_declaring_class) + void SetDeclaringClass(ObjPtr new_declaring_class) REQUIRES_SHARED(Locks::mutator_lock_); uint32_t GetAccessFlags() REQUIRES_SHARED(Locks::mutator_lock_); @@ -87,68 +86,72 @@ class ArtField FINAL { void SetOffset(MemberOffset num_bytes) REQUIRES_SHARED(Locks::mutator_lock_); // field access, null object for static fields - uint8_t GetBoolean(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + uint8_t GetBoolean(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void SetBoolean(mirror::Object* object, uint8_t z) REQUIRES_SHARED(Locks::mutator_lock_); + void SetBoolean(ObjPtr object, uint8_t z) REQUIRES_SHARED(Locks::mutator_lock_); - int8_t GetByte(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + int8_t GetByte(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void SetByte(mirror::Object* object, int8_t b) REQUIRES_SHARED(Locks::mutator_lock_); + void SetByte(ObjPtr object, int8_t b) REQUIRES_SHARED(Locks::mutator_lock_); - uint16_t GetChar(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + uint16_t GetChar(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void SetChar(mirror::Object* object, uint16_t c) REQUIRES_SHARED(Locks::mutator_lock_); + void SetChar(ObjPtr object, uint16_t c) REQUIRES_SHARED(Locks::mutator_lock_); - int16_t GetShort(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + int16_t GetShort(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void SetShort(mirror::Object* object, int16_t s) REQUIRES_SHARED(Locks::mutator_lock_); + void SetShort(ObjPtr object, int16_t s) REQUIRES_SHARED(Locks::mutator_lock_); - int32_t GetInt(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + int32_t GetInt(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void SetInt(mirror::Object* object, int32_t i) REQUIRES_SHARED(Locks::mutator_lock_); + void SetInt(ObjPtr object, int32_t i) REQUIRES_SHARED(Locks::mutator_lock_); - int64_t GetLong(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + int64_t GetLong(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void SetLong(mirror::Object* object, int64_t j) REQUIRES_SHARED(Locks::mutator_lock_); + void SetLong(ObjPtr object, int64_t j) REQUIRES_SHARED(Locks::mutator_lock_); - float GetFloat(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + float GetFloat(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void SetFloat(mirror::Object* object, float f) REQUIRES_SHARED(Locks::mutator_lock_); + void SetFloat(ObjPtr object, float f) REQUIRES_SHARED(Locks::mutator_lock_); - double GetDouble(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + double GetDouble(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void SetDouble(mirror::Object* object, double d) REQUIRES_SHARED(Locks::mutator_lock_); + void SetDouble(ObjPtr object, double d) REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetObject(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr GetObject(ObjPtr object) + REQUIRES_SHARED(Locks::mutator_lock_); template - void SetObject(mirror::Object* object, mirror::Object* l) + void SetObject(ObjPtr object, ObjPtr l) REQUIRES_SHARED(Locks::mutator_lock_); // Raw field accesses. - uint32_t Get32(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + uint32_t Get32(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void Set32(mirror::Object* object, uint32_t new_value) + void Set32(ObjPtr object, uint32_t new_value) REQUIRES_SHARED(Locks::mutator_lock_); - uint64_t Get64(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + uint64_t Get64(ObjPtr object) REQUIRES_SHARED(Locks::mutator_lock_); template - void Set64(mirror::Object* object, uint64_t new_value) REQUIRES_SHARED(Locks::mutator_lock_); + void Set64(ObjPtr object, uint64_t new_value) + REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Object* GetObj(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_); + template + ObjPtr GetObj(ObjPtr object) + REQUIRES_SHARED(Locks::mutator_lock_); template - void SetObj(mirror::Object* object, mirror::Object* new_value) + void SetObj(ObjPtr object, ObjPtr new_value) REQUIRES_SHARED(Locks::mutator_lock_); // NO_THREAD_SAFETY_ANALYSIS since we don't know what the callback requires. @@ -163,20 +166,20 @@ class ArtField FINAL { // If kExactOffset is true then we only find the matching offset, not the field containing the // offset. template - static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) + static ArtField* FindInstanceFieldWithOffset(ObjPtr klass, uint32_t field_offset) REQUIRES_SHARED(Locks::mutator_lock_); // Returns a static field with this offset in the given class or null if not found. // If kExactOffset is true then we only find the matching offset, not the field containing the // offset. template - static ArtField* FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) + static ArtField* FindStaticFieldWithOffset(ObjPtr klass, uint32_t field_offset) REQUIRES_SHARED(Locks::mutator_lock_); const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_); // Resolves / returns the name from the dex cache. - mirror::String* GetStringName(Thread* self, bool resolve) + ObjPtr GetStringName(Thread* self, bool resolve) REQUIRES_SHARED(Locks::mutator_lock_); const char* GetTypeDescriptor() REQUIRES_SHARED(Locks::mutator_lock_); @@ -186,11 +189,11 @@ class ArtField FINAL { bool IsPrimitiveType() REQUIRES_SHARED(Locks::mutator_lock_); template - mirror::Class* GetType() REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr GetType() REQUIRES_SHARED(Locks::mutator_lock_); size_t FieldSize() REQUIRES_SHARED(Locks::mutator_lock_); - mirror::DexCache* GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_); const DexFile* GetDexFile() REQUIRES_SHARED(Locks::mutator_lock_); @@ -204,22 +207,24 @@ class ArtField FINAL { REQUIRES_SHARED(Locks::mutator_lock_); private: - mirror::Class* ProxyFindSystemClass(const char* descriptor) + ObjPtr ProxyFindSystemClass(const char* descriptor) REQUIRES_SHARED(Locks::mutator_lock_); - mirror::Class* ResolveGetType(uint32_t type_idx) REQUIRES_SHARED(Locks::mutator_lock_); - mirror::String* ResolveGetStringName(Thread* self, const DexFile& dex_file, uint32_t string_idx, - mirror::DexCache* dex_cache) + ObjPtr ResolveGetType(uint32_t type_idx) REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr ResolveGetStringName(Thread* self, + const DexFile& dex_file, + uint32_t string_idx, + ObjPtr dex_cache) REQUIRES_SHARED(Locks::mutator_lock_); GcRoot declaring_class_; - uint32_t access_flags_; + uint32_t access_flags_ = 0; // Dex cache index of field id - uint32_t field_dex_idx_; + uint32_t field_dex_idx_ = 0; // Offset of field within an instance or in the Class' static fields - uint32_t offset_; + uint32_t offset_ = 0; }; } // namespace art diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index 9f0770285..c671b81db 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -274,7 +274,7 @@ class ScopedCheck { AbortF("field operation on NULL object: %p", java_object); return false; } - if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Decode())) { + if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); AbortF("field operation on invalid %s: %p", ToStr(GetIndirectRefKind(java_object)).c_str(), @@ -334,7 +334,7 @@ class ScopedCheck { } if (invoke != kVirtual) { ObjPtr c = soa.Decode(jc); - if (!m->GetDeclaringClass()->IsAssignableFrom(c.Decode())) { + if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual", PrettyMethod(m).c_str(), PrettyClass(c).c_str()); return false; @@ -388,7 +388,7 @@ class ScopedCheck { return false; } ObjPtr c = soa.Decode(java_class); - if (!m->GetDeclaringClass()->IsAssignableFrom(c.Decode())) { + if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str()); return false; } @@ -939,7 +939,7 @@ class ScopedCheck { ObjPtr c = soa.Decode(jc); if (c == nullptr) { *msg += "NULL"; - } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Decode())) { + } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) { StringAppendF(msg, "INVALID POINTER:%p", jc); } else if (!c->IsClass()) { *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c); @@ -1108,7 +1108,7 @@ class ScopedCheck { } ObjPtr a = soa.Decode(java_array); - if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Decode()))) { + if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) { Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); AbortF("jarray is an invalid %s: %p (%p)", ToStr(GetIndirectRefKind(java_array)).c_str(), diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 51e5aae3d..378da57bb 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -63,6 +63,7 @@ inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class** } inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, ArtMethod* referrer) { + Thread::PoisonObjectPointersIfDebug(); mirror::Class* declaring_class = referrer->GetDeclaringClass(); // MethodVerifier refuses methods with string_idx out of bounds. DCHECK_LT(string_idx, declaring_class->GetDexFile().NumStringIds());; @@ -70,7 +71,6 @@ inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, ArtMethod mirror::StringDexCachePair::Lookup(declaring_class->GetDexCacheStrings(), string_idx, mirror::DexCache::kDexCacheStringCacheSize).Read(); - Thread::PoisonObjectPointersIfDebug(); if (UNLIKELY(string == nullptr)) { StackHandleScope<1> hs(Thread::Current()); Handle dex_cache(hs.NewHandle(declaring_class->GetDexCache())); @@ -84,8 +84,8 @@ inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, ArtMethod } inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtMethod* referrer) { - mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx, image_pointer_size_); Thread::PoisonObjectPointersIfDebug(); + mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx, image_pointer_size_); if (UNLIKELY(resolved_type == nullptr)) { mirror::Class* declaring_class = referrer->GetDeclaringClass(); StackHandleScope<2> hs(Thread::Current()); @@ -100,10 +100,10 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtMethod* ref } inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtField* referrer) { - mirror::Class* declaring_class = referrer->GetDeclaringClass(); + Thread::PoisonObjectPointersIfDebug(); + ObjPtr declaring_class = referrer->GetDeclaringClass(); mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache(); mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx); - Thread::PoisonObjectPointersIfDebug(); if (UNLIKELY(resolved_type == nullptr)) { StackHandleScope<2> hs(Thread::Current()); Handle dex_cache(hs.NewHandle(dex_cache_ptr)); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 7dea614fd..06a824336 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1090,7 +1090,7 @@ bool ClassLinker::IsBootClassLoader(ScopedObjectAccessAlreadyRunnable& soa, } static mirror::String* GetDexPathListElementName(ScopedObjectAccessUnchecked& soa, - mirror::Object* element) + ObjPtr element) REQUIRES_SHARED(Locks::mutator_lock_) { ArtField* const dex_file_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); @@ -1100,11 +1100,11 @@ static mirror::String* GetDexPathListElementName(ScopedObjectAccessUnchecked& so DCHECK(dex_file_name_field != nullptr); DCHECK(element != nullptr); CHECK_EQ(dex_file_field->GetDeclaringClass(), element->GetClass()) << PrettyTypeOf(element); - mirror::Object* dex_file = dex_file_field->GetObject(element); + ObjPtr dex_file = dex_file_field->GetObject(element); if (dex_file == nullptr) { return nullptr; } - mirror::Object* const name_object = dex_file_name_field->GetObject(dex_file); + ObjPtr name_object = dex_file_name_field->GetObject(dex_file); if (name_object != nullptr) { return name_object->AsString(); } @@ -1131,28 +1131,28 @@ static bool FlattenPathClassLoader(mirror::ClassLoader* class_loader, // Unsupported class loader. return false; } - mirror::Object* dex_path_list = dex_path_list_field->GetObject(class_loader); + ObjPtr dex_path_list = dex_path_list_field->GetObject(class_loader); if (dex_path_list != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. - mirror::Object* dex_elements_obj = dex_elements_field->GetObject(dex_path_list); + ObjPtr dex_elements_obj = dex_elements_field->GetObject(dex_path_list); // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look // at the mCookie which is a DexFile vector. if (dex_elements_obj != nullptr) { - mirror::ObjectArray* dex_elements = + ObjPtr> dex_elements = dex_elements_obj->AsObjectArray(); // Reverse order since we insert the parent at the front. for (int32_t i = dex_elements->GetLength() - 1; i >= 0; --i) { - mirror::Object* const element = dex_elements->GetWithoutChecks(i); + ObjPtr element = dex_elements->GetWithoutChecks(i); if (element == nullptr) { *error_msg = StringPrintf("Null dex element at index %d", i); return false; } - mirror::String* const name = GetDexPathListElementName(soa, element); + ObjPtr const name = GetDexPathListElementName(soa, element); if (name == nullptr) { *error_msg = StringPrintf("Null name for dex element at index %d", i); return false; } - out_dex_file_names->push_front(name); + out_dex_file_names->push_front(name.Decode()); } } } @@ -2395,12 +2395,12 @@ bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& ArtField* const cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); ArtField* const dex_file_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); - mirror::Object* dex_path_list = + ObjPtr dex_path_list = soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> GetObject(class_loader.Get()); if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. - mirror::Object* dex_elements_obj = + ObjPtr dex_elements_obj = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> GetObject(dex_path_list); // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look @@ -2409,14 +2409,14 @@ bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& Handle> dex_elements = hs.NewHandle(dex_elements_obj->AsObjectArray()); for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { - mirror::Object* element = dex_elements->GetWithoutChecks(i); + ObjPtr element = dex_elements->GetWithoutChecks(i); if (element == nullptr) { // Should never happen, fall back to java code to throw a NPE. break; } - mirror::Object* dex_file = dex_file_field->GetObject(element); + ObjPtr dex_file = dex_file_field->GetObject(element); if (dex_file != nullptr) { - mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray(); + ObjPtr long_array = cookie_field->GetObject(dex_file)->AsLongArray(); if (long_array == nullptr) { // This should never happen so log a warning. LOG(WARNING) << "Null DexFile::mCookie for " << descriptor; @@ -8256,16 +8256,18 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, ScopedObjectAccessUnchecked soa(self); // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex. - StackHandleScope<10> hs(self); + StackHandleScope<11> hs(self); ArtField* dex_elements_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements); - mirror::Class* dex_elements_class = dex_elements_field->GetType(); - DCHECK(dex_elements_class != nullptr); + Handle dex_elements_class(hs.NewHandle(dex_elements_field->GetType())); + DCHECK(dex_elements_class.Get() != nullptr); DCHECK(dex_elements_class->IsArrayClass()); Handle> h_dex_elements(hs.NewHandle( - mirror::ObjectArray::Alloc(self, dex_elements_class, dex_files.size()))); + mirror::ObjectArray::Alloc(self, + dex_elements_class.Get(), + dex_files.size()))); Handle h_dex_element_class = hs.NewHandle(dex_elements_class->GetComponentType()); diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 451b752ee..3c12b18f9 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -243,10 +243,10 @@ class ClassLinkerTest : public CommonRuntimeTest { kRuntimePointerSize)); } - void AssertField(mirror::Class* klass, ArtField* field) + void AssertField(ObjPtr klass, ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) { EXPECT_TRUE(field != nullptr); - EXPECT_EQ(klass, field->GetDeclaringClass()); + EXPECT_OBJ_PTR_EQ(klass, field->GetDeclaringClass()); EXPECT_TRUE(field->GetName() != nullptr); EXPECT_TRUE(field->GetType() != nullptr); } @@ -358,7 +358,7 @@ class ClassLinkerTest : public CommonRuntimeTest { MemberOffset current_ref_offset = start_ref_offset; for (size_t i = 0; i < klass->NumInstanceFields(); i++) { ArtField* field = klass->GetInstanceField(i); - mirror::Class* field_type = field->GetType(); + ObjPtr field_type = field->GetType(); ASSERT_TRUE(field_type != nullptr); if (!field->IsPrimitiveType()) { ASSERT_TRUE(!field_type->IsPrimitive()); @@ -1018,8 +1018,8 @@ TEST_F(ClassLinkerTest, StaticFields) { "Ljava/lang/String;"); EXPECT_EQ(s8->GetTypeAsPrimitiveType(), Primitive::kPrimNot); EXPECT_TRUE(s8->GetObject(statics.Get())->AsString()->Equals("android")); - s8->SetObject(s8->GetDeclaringClass(), - mirror::String::AllocFromModifiedUtf8(soa.Self(), "robot")); + mirror::String* str_value = mirror::String::AllocFromModifiedUtf8(soa.Self(), "robot"); + s8->SetObject(s8->GetDeclaringClass(), str_value); // TODO: Remove EXPECT_FALSE when GCC can handle EXPECT_EQ // http://code.google.com/p/googletest/issues/detail?id=322 diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index eda1ddd87..ea0719502 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -523,12 +523,12 @@ std::vector CommonRuntimeTestImpl::GetDexFiles(jobject jclass_lo ArtField* cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); ArtField* dex_file_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); - mirror::Object* dex_path_list = + ObjPtr dex_path_list = soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> GetObject(class_loader.Get()); if (dex_path_list != nullptr && dex_file_field!= nullptr && cookie_field != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. - mirror::Object* dex_elements_obj = + ObjPtr dex_elements_obj = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> GetObject(dex_path_list); // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look @@ -537,14 +537,14 @@ std::vector CommonRuntimeTestImpl::GetDexFiles(jobject jclass_lo Handle> dex_elements = hs.NewHandle(dex_elements_obj->AsObjectArray()); for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { - mirror::Object* element = dex_elements->GetWithoutChecks(i); + ObjPtr element = dex_elements->GetWithoutChecks(i); if (element == nullptr) { // Should never happen, fall back to java code to throw a NPE. break; } - mirror::Object* dex_file = dex_file_field->GetObject(element); + ObjPtr dex_file = dex_file_field->GetObject(element); if (dex_file != nullptr) { - mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray(); + ObjPtr long_array = cookie_field->GetObject(dex_file)->AsLongArray(); DCHECK(long_array != nullptr); int32_t long_array_size = long_array->GetLength(); for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) { diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h index a7948e4e8..2158d81b4 100644 --- a/runtime/common_runtime_test.h +++ b/runtime/common_runtime_test.h @@ -25,10 +25,18 @@ #include "arch/instruction_set.h" #include "base/mutex.h" #include "globals.h" +// TODO: Add inl file and avoid including inl. +#include "obj_ptr-inl.h" #include "os.h" namespace art { +// OBJ pointer helpers to avoid needing .Decode everywhere. +#define EXPECT_OBJ_PTR_EQ(a, b) EXPECT_EQ(MakeObjPtr(a).Decode(), MakeObjPtr(b).Decode()); +#define ASSERT_OBJ_PTR_EQ(a, b) ASSERT_EQ(MakeObjPtr(a).Decode(), MakeObjPtr(b).Decode()); +#define EXPECT_OBJ_PTR_NE(a, b) EXPECT_NE(MakeObjPtr(a).Decode(), MakeObjPtr(b).Decode()); +#define ASSERT_OBJ_PTR_NE(a, b) ASSERT_NE(MakeObjPtr(a).Decode(), MakeObjPtr(b).Decode()); + class ClassLinker; class CompilerCallbacks; class DexFile; diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 0206caef4..1bdb0fccd 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -46,6 +46,7 @@ #include "mirror/object_array-inl.h" #include "mirror/string-inl.h" #include "mirror/throwable.h" +#include "obj_ptr-inl.h" #include "reflection.h" #include "safe_map.h" #include "scoped_thread_state_change-inl.h" @@ -985,7 +986,7 @@ void Dbg::DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) { gRegistry->DisposeObject(object_id, reference_count); } -JDWP::JdwpTypeTag Dbg::GetTypeTag(mirror::Class* klass) { +JDWP::JdwpTypeTag Dbg::GetTypeTag(ObjPtr klass) { DCHECK(klass != nullptr); if (klass->IsArrayClass()) { return JDWP::TT_ARRAY; @@ -1367,12 +1368,12 @@ bool Dbg::MatchLocation(const JDWP::JdwpLocation& expected_location, return m == event_location.method; } -bool Dbg::MatchType(mirror::Class* event_class, JDWP::RefTypeId class_id) { +bool Dbg::MatchType(ObjPtr event_class, JDWP::RefTypeId class_id) { if (event_class == nullptr) { return false; } JDWP::JdwpError error; - mirror::Class* expected_class = DecodeClass(class_id, &error); + ObjPtr expected_class = DecodeClass(class_id, &error); CHECK(expected_class != nullptr); return expected_class->IsAssignableFrom(event_class); } @@ -1742,7 +1743,7 @@ static JValue GetArtFieldValue(ArtField* f, mirror::Object* o) return field_value; case Primitive::kPrimNot: - field_value.SetL(f->GetObject(o)); + field_value.SetL(f->GetObject(o).Decode()); return field_value; case Primitive::kPrimVoid: @@ -1868,7 +1869,7 @@ static JDWP::JdwpError SetArtFieldValue(ArtField* f, mirror::Object* o, uint64_t return JDWP::ERR_INVALID_OBJECT; } if (v != nullptr) { - mirror::Class* field_type; + ObjPtr field_type; { StackHandleScope<2> hs(Thread::Current()); HandleWrapper h_v(hs.NewHandleWrapper(&v)); @@ -1994,8 +1995,7 @@ JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) CHECK(thread_object != nullptr) << error; ArtField* java_lang_Thread_name_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); - mirror::String* s = - reinterpret_cast(java_lang_Thread_name_field->GetObject(thread_object)); + ObjPtr s(java_lang_Thread_name_field->GetObject(thread_object)); if (s != nullptr) { *name = s->ToModifiedUtf8(); } @@ -2021,7 +2021,7 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p CHECK(c != nullptr); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_group); CHECK(f != nullptr); - mirror::Object* group = f->GetObject(thread_object); + ObjPtr group = f->GetObject(thread_object); CHECK(group != nullptr); JDWP::ObjectId thread_group_id = gRegistry->Add(group); expandBufAddObjectId(pReply, thread_group_id); @@ -2063,7 +2063,7 @@ JDWP::JdwpError Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id, JDWP::Ex ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupName"); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); CHECK(f != nullptr); - mirror::String* s = reinterpret_cast(f->GetObject(thread_group)); + ObjPtr s = f->GetObject(thread_group)->AsString(); std::string thread_group_name(s->ToModifiedUtf8()); expandBufAddUtf8String(pReply, thread_group_name); @@ -2077,7 +2077,7 @@ JDWP::JdwpError Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id, JDWP:: if (error != JDWP::ERR_NONE) { return error; } - mirror::Object* parent; + ObjPtr parent; { ScopedAssertNoThreadSuspension ants("Debugger: GetThreadGroupParent"); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_parent); @@ -2104,12 +2104,12 @@ static void GetChildThreadGroups(ScopedObjectAccessUnchecked& soa, mirror::Objec // Get the ThreadGroup[] "groups" out of this thread group... ArtField* groups_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_groups); - mirror::Object* groups_array = groups_field->GetObject(thread_group); + ObjPtr groups_array = groups_field->GetObject(thread_group); CHECK(groups_array != nullptr); CHECK(groups_array->IsObjectArray()); - mirror::ObjectArray* groups_array_as_array = + ObjPtr> groups_array_as_array = groups_array->AsObjectArray(); // Copy the first 'size' elements out of the array into the result. @@ -2154,7 +2154,7 @@ JDWP::JdwpError Dbg::GetThreadGroupChildren(JDWP::ObjectId thread_group_id, JDWP::ObjectId Dbg::GetSystemThreadGroupId() { ScopedObjectAccessUnchecked soa(Thread::Current()); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); - mirror::Object* group = f->GetObject(f->GetDeclaringClass()); + ObjPtr group = f->GetObject(f->GetDeclaringClass()); return gRegistry->Add(group); } @@ -2252,7 +2252,7 @@ static bool IsInDesiredThreadGroup(ScopedObjectAccessUnchecked& soa, } ArtField* thread_group_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_group); DCHECK(thread_group_field != nullptr); - mirror::Object* group = thread_group_field->GetObject(peer); + ObjPtr group = thread_group_field->GetObject(peer); return (group == desired_thread_group); } diff --git a/runtime/debugger.h b/runtime/debugger.h index 7398c4e76..5d0315e9a 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -31,6 +31,7 @@ #include "jdwp/jdwp.h" #include "jni.h" #include "jvalue.h" +#include "obj_ptr.h" #include "thread.h" #include "thread_state.h" @@ -317,7 +318,7 @@ class Dbg { const JDWP::EventLocation& event_location) REQUIRES_SHARED(Locks::mutator_lock_); - static bool MatchType(mirror::Class* event_class, JDWP::RefTypeId class_id) + static bool MatchType(ObjPtr event_class, JDWP::RefTypeId class_id) REQUIRES_SHARED(Locks::mutator_lock_); static bool MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id, @@ -689,7 +690,7 @@ class Dbg { static JDWP::JdwpTag TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o) REQUIRES_SHARED(Locks::mutator_lock_); - static JDWP::JdwpTypeTag GetTypeTag(mirror::Class* klass) + static JDWP::JdwpTypeTag GetTypeTag(ObjPtr klass) REQUIRES_SHARED(Locks::mutator_lock_); static JDWP::FieldId ToFieldId(const ArtField* f) diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc index 5763479fe..feb75a829 100644 --- a/runtime/dex_file_annotations.cc +++ b/runtime/dex_file_annotations.cc @@ -54,7 +54,7 @@ bool IsVisibilityCompatible(uint32_t actual, uint32_t expected) { const DexFile::AnnotationSetItem* FindAnnotationSetForField(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) { const DexFile* dex_file = field->GetDexFile(); - mirror::Class* klass = field->GetDeclaringClass(); + ObjPtr klass = field->GetDeclaringClass(); const DexFile::AnnotationsDirectoryItem* annotations_dir = dex_file->GetAnnotationsDirectory(*klass->GetClassDef()); if (annotations_dir == nullptr) { @@ -302,7 +302,7 @@ bool ProcessAnnotationValue(Handle klass, REQUIRES_SHARED(Locks::mutator_lock_) { const DexFile& dex_file = klass->GetDexFile(); Thread* self = Thread::Current(); - mirror::Object* element_object = nullptr; + ObjPtr element_object = nullptr; bool set_object = false; Primitive::Type primitive_type = Primitive::kPrimVoid; const uint8_t* annotation = *annotation_ptr; @@ -577,7 +577,7 @@ bool ProcessAnnotationValue(Handle klass, } if (set_object) { - annotation_value->value_.SetL(element_object); + annotation_value->value_.SetL(element_object.Decode()); } return true; diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 99b880509..e37db7dd9 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -410,14 +410,15 @@ inline ArtField* FindFieldFromCode(uint32_t field_idx, DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. } - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + ObjPtr fields_class = resolved_field->GetDeclaringClass(); if (access_check) { if (UNLIKELY(resolved_field->IsStatic() != is_static)) { ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer); return nullptr; } mirror::Class* referring_class = referrer->GetDeclaringClass(); - if (UNLIKELY(!referring_class->CheckResolvedFieldAccess(fields_class, resolved_field, + if (UNLIKELY(!referring_class->CheckResolvedFieldAccess(fields_class, + resolved_field, field_idx))) { DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. @@ -696,7 +697,7 @@ inline ArtField* FindFieldFast(uint32_t field_idx, ArtMethod* referrer, FindFiel // Incompatible class change. return nullptr; } - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); + ObjPtr fields_class = resolved_field->GetDeclaringClass(); if (is_static) { // Check class is initialized else fail so that we can contend to initialize the class with // other threads that may be racing to do this. diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc index 5b65029df..70eb1de87 100644 --- a/runtime/entrypoints/quick/quick_field_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc @@ -151,14 +151,14 @@ extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx, StaticObjectRead, sizeof(mirror::HeapReference)); if (LIKELY(field != nullptr)) { - return field->GetObj(field->GetDeclaringClass()); + return field->GetObj(field->GetDeclaringClass()).Decode(); } field = FindFieldFromCode(field_idx, referrer, self, sizeof(mirror::HeapReference)); if (LIKELY(field != nullptr)) { - return field->GetObj(field->GetDeclaringClass()); + return field->GetObj(field->GetDeclaringClass()).Decode(); } return nullptr; // Will throw exception by checking with Thread::Current. } @@ -299,7 +299,7 @@ extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, InstanceObjectRead, sizeof(mirror::HeapReference)); if (LIKELY(field != nullptr && obj != nullptr)) { - return field->GetObj(obj); + return field->GetObj(obj).Decode(); } field = FindInstanceField(field_idx, referrer, @@ -307,7 +307,7 @@ extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, sizeof(mirror::HeapReference), &obj); if (LIKELY(field != nullptr)) { - return field->GetObj(obj); + return field->GetObj(obj).Decode(); } return nullptr; // Will throw exception by checking with Thread::Current. } diff --git a/runtime/gc_root-inl.h b/runtime/gc_root-inl.h index ae8a38f43..11ccd33bc 100644 --- a/runtime/gc_root-inl.h +++ b/runtime/gc_root-inl.h @@ -21,6 +21,7 @@ #include +#include "obj_ptr-inl.h" #include "read_barrier-inl.h" namespace art { @@ -31,10 +32,15 @@ inline MirrorType* GcRoot::Read(GcRootSource* gc_root_source) const return down_cast( ReadBarrier::BarrierForRoot(&root_, gc_root_source)); } + template inline GcRoot::GcRoot(MirrorType* ref) : root_(mirror::CompressedReference::FromMirrorPtr(ref)) { } +template +inline GcRoot::GcRoot(ObjPtr ref) + : GcRoot(ref.Decode()) { } + inline std::string RootInfo::ToString() const { std::ostringstream oss; Describe(oss); diff --git a/runtime/gc_root.h b/runtime/gc_root.h index 0a98f5582..85cd0a471 100644 --- a/runtime/gc_root.h +++ b/runtime/gc_root.h @@ -24,6 +24,7 @@ namespace art { class ArtField; class ArtMethod; +template class ObjPtr; namespace mirror { class Object; @@ -196,7 +197,10 @@ class GcRoot { } ALWAYS_INLINE GcRoot() {} - explicit ALWAYS_INLINE GcRoot(MirrorType* ref) REQUIRES_SHARED(Locks::mutator_lock_); + explicit ALWAYS_INLINE GcRoot(MirrorType* ref) + REQUIRES_SHARED(Locks::mutator_lock_); + explicit ALWAYS_INLINE GcRoot(ObjPtr ref) + REQUIRES_SHARED(Locks::mutator_lock_); private: // Root visitors take pointers to root_ and place them in CompressedReference** arrays. We use a diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h index 75a039108..1814746d7 100644 --- a/runtime/handle_scope-inl.h +++ b/runtime/handle_scope-inl.h @@ -135,6 +135,12 @@ inline void StackHandleScope::SetReference(size_t i, mirror::Obj GetReferences()[i].Assign(object); } +template +inline MutableHandle StackHandleScopeCollection::NewHandle( + ObjPtr ptr) { + return NewHandle(ptr.Decode()); +} + } // namespace art #endif // ART_RUNTIME_HANDLE_SCOPE_INL_H_ diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h index 2b283ae3d..fc729a547 100644 --- a/runtime/handle_scope.h +++ b/runtime/handle_scope.h @@ -252,6 +252,10 @@ class StackHandleScopeCollection { return scopes_.top()->NewHandle(object); } + template + MutableHandle NewHandle(ObjPtr ptr) + REQUIRES_SHARED(Locks::mutator_lock_); + private: static constexpr size_t kNumReferencesPerScope = 4; diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 5934f13b3..6c8e53df8 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -46,7 +46,7 @@ bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst CHECK(self->IsExceptionPending()); return false; } - Object* obj; + ObjPtr obj; if (is_static) { obj = f->GetDeclaringClass(); } else { @@ -60,9 +60,15 @@ bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst // Report this field access to instrumentation if needed. instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); if (UNLIKELY(instrumentation->HasFieldReadListeners())) { - Object* this_object = f->IsStatic() ? nullptr : obj; - instrumentation->FieldReadEvent(self, this_object, shadow_frame.GetMethod(), - shadow_frame.GetDexPC(), f); + ObjPtr this_object; + if (!f->IsStatic()) { + this_object = obj; + } + instrumentation->FieldReadEvent(self, + this_object.Decode(), + shadow_frame.GetMethod(), + shadow_frame.GetDexPC(), + f); } uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data); switch (field_type) { @@ -85,7 +91,7 @@ bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst shadow_frame.SetVRegLong(vregA, f->GetLong(obj)); break; case Primitive::kPrimNot: - shadow_frame.SetVRegReference(vregA, f->GetObject(obj)); + shadow_frame.SetVRegReference(vregA, f->GetObject(obj).Decode()); break; default: LOG(FATAL) << "Unreachable: " << field_type; @@ -241,7 +247,7 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction CHECK(self->IsExceptionPending()); return false; } - Object* obj; + ObjPtr obj; if (is_static) { obj = f->GetDeclaringClass(); } else { @@ -258,9 +264,12 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); if (UNLIKELY(instrumentation->HasFieldWriteListeners())) { JValue field_value = GetFieldValue(shadow_frame, vregA); - Object* this_object = f->IsStatic() ? nullptr : obj; - instrumentation->FieldWriteEvent(self, this_object, shadow_frame.GetMethod(), - shadow_frame.GetDexPC(), f, field_value); + ObjPtr this_object = f->IsStatic() ? nullptr : obj; + instrumentation->FieldWriteEvent(self, this_object.Decode(), + shadow_frame.GetMethod(), + shadow_frame.GetDexPC(), + f, + field_value); } switch (field_type) { case Primitive::kPrimBoolean: @@ -286,14 +295,14 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction if (do_assignability_check && reg != nullptr) { // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the // object in the destructor. - Class* field_class; + ObjPtr field_class; { StackHandleScope<2> hs(self); HandleWrapper h_reg(hs.NewHandleWrapper(®)); - HandleWrapper h_obj(hs.NewHandleWrapper(&obj)); + HandleWrapperObjPtr h_obj(hs.NewHandleWrapper(&obj)); field_class = f->GetType(); } - if (!reg->VerifierInstanceOf(field_class)) { + if (!reg->VerifierInstanceOf(field_class.Decode())) { // This should never happen. std::string temp1, temp2, temp3; self->ThrowNewExceptionF("Ljava/lang/VirtualMachineError;", diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 39846da46..eb8cdbc70 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -786,9 +786,9 @@ static void GetSystemProperty(Thread* self, kAndroidHardcodedSystemPropertiesFieldName); return; } - Handle>> h_2string_array( - hs.NewHandle(reinterpret_cast>*>( - static_properties->GetObject(h_props_class.Get())))); + ObjPtr props = static_properties->GetObject(h_props_class.Get()); + Handle>> h_2string_array(hs.NewHandle( + props->AsObjectArray>())); if (h_2string_array.Get() == nullptr) { AbortTransactionOrFail(self, "Field %s is null", kAndroidHardcodedSystemPropertiesFieldName); return; diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc index 9ba62c93c..dc3bf16a0 100644 --- a/runtime/jdwp/object_registry.cc +++ b/runtime/jdwp/object_registry.cc @@ -19,6 +19,7 @@ #include "handle_scope-inl.h" #include "jni_internal.h" #include "mirror/class.h" +#include "obj_ptr-inl.h" #include "scoped_thread_state_change-inl.h" namespace art { @@ -35,7 +36,7 @@ ObjectRegistry::ObjectRegistry() : lock_("ObjectRegistry lock", kJdwpObjectRegistryLock), next_id_(1) { } -JDWP::RefTypeId ObjectRegistry::AddRefType(mirror::Class* c) { +JDWP::RefTypeId ObjectRegistry::AddRefType(ObjPtr c) { return Add(c); } @@ -43,7 +44,7 @@ JDWP::RefTypeId ObjectRegistry::AddRefType(Handle c_h) { return Add(c_h); } -JDWP::ObjectId ObjectRegistry::Add(mirror::Object* o) { +JDWP::ObjectId ObjectRegistry::Add(ObjPtr o) { if (o == nullptr) { return 0; } @@ -118,7 +119,9 @@ JDWP::ObjectId ObjectRegistry::InternalAdd(Handle obj_h) { return entry->id; } -bool ObjectRegistry::ContainsLocked(Thread* self, mirror::Object* o, int32_t identity_hash_code, +bool ObjectRegistry::ContainsLocked(Thread* self, + ObjPtr o, + int32_t identity_hash_code, ObjectRegistryEntry** out_entry) { DCHECK(o != nullptr); for (auto it = object_to_entry_.lower_bound(identity_hash_code), end = object_to_entry_.end(); diff --git a/runtime/jdwp/object_registry.h b/runtime/jdwp/object_registry.h index 7fa57c637..9cacc66c3 100644 --- a/runtime/jdwp/object_registry.h +++ b/runtime/jdwp/object_registry.h @@ -25,6 +25,7 @@ #include "base/casts.h" #include "handle.h" #include "jdwp/jdwp.h" +#include "obj_ptr.h" #include "safe_map.h" namespace art { @@ -62,11 +63,11 @@ class ObjectRegistry { public: ObjectRegistry(); - JDWP::ObjectId Add(mirror::Object* o) + JDWP::ObjectId Add(ObjPtr o) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !lock_); - JDWP::RefTypeId AddRefType(mirror::Class* c) + JDWP::RefTypeId AddRefType(ObjPtr c) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !lock_); @@ -121,7 +122,9 @@ class ObjectRegistry { void Promote(ObjectRegistryEntry& entry) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(lock_); - bool ContainsLocked(Thread* self, mirror::Object* o, int32_t identity_hash_code, + bool ContainsLocked(Thread* self, + ObjPtr o, + int32_t identity_hash_code, ObjectRegistryEntry** out_entry) REQUIRES(lock_) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 7b2757897..797781506 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -97,15 +97,20 @@ static void ThrowNoSuchMethodError(ScopedObjectAccess& soa, mirror::Class* c, kind, c->GetDescriptor(&temp), name, sig); } -static void ReportInvalidJNINativeMethod(const ScopedObjectAccess& soa, mirror::Class* c, - const char* kind, jint idx, bool return_errors) +static void ReportInvalidJNINativeMethod(const ScopedObjectAccess& soa, + ObjPtr c, + const char* kind, + jint idx, + bool return_errors) REQUIRES_SHARED(Locks::mutator_lock_) { LOG(return_errors ? ::android::base::ERROR : ::android::base::FATAL) << "Failed to register native method in " << PrettyDescriptor(c) << " in " << c->GetDexCache()->GetLocation()->ToModifiedUtf8() << ": " << kind << " is null at index " << idx; soa.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;", - "%s is null at index %d", kind, idx); + "%s is null at index %d", + kind, + idx); } static ObjPtr EnsureInitialized(Thread* self, ObjPtr klass) @@ -282,7 +287,7 @@ int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobj return JNI_ERR; } ScopedObjectAccess soa(env); - soa.Self()->SetException(soa.Decode(exception.get()).Decode()); + soa.Self()->SetException(soa.Decode(exception.get())); return JNI_OK; } @@ -417,7 +422,7 @@ class JNI { ScopedObjectAccess soa(env); ObjPtr c1 = soa.Decode(java_class1); ObjPtr c2 = soa.Decode(java_class2); - return c2->IsAssignableFrom(c1.Decode()) ? JNI_TRUE : JNI_FALSE; + return c2->IsAssignableFrom(c1) ? JNI_TRUE : JNI_FALSE; } static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) { @@ -439,7 +444,7 @@ class JNI { if (exception == nullptr) { return JNI_ERR; } - soa.Self()->SetException(exception.Decode()); + soa.Self()->SetException(exception); return JNI_OK; } @@ -1227,7 +1232,7 @@ class JNI { ScopedObjectAccess soa(env); ObjPtr o = soa.Decode(obj); ArtField* f = soa.DecodeField(fid); - return soa.AddLocalReference(f->GetObject(o.Decode())); + return soa.AddLocalReference(f->GetObject(o)); } static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) { @@ -1244,7 +1249,7 @@ class JNI { ObjPtr o = soa.Decode(java_object); ObjPtr v = soa.Decode(java_value); ArtField* f = soa.DecodeField(fid); - f->SetObject(o.Decode(), v.Decode()); + f->SetObject(o, v); } static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) { @@ -1252,7 +1257,7 @@ class JNI { ScopedObjectAccess soa(env); ObjPtr v = soa.Decode(java_value); ArtField* f = soa.DecodeField(fid); - f->SetObject(f->GetDeclaringClass(), v.Decode()); + f->SetObject(f->GetDeclaringClass(), v); } #define GET_PRIMITIVE_FIELD(fn, instance) \ @@ -1261,7 +1266,7 @@ class JNI { ScopedObjectAccess soa(env); \ ObjPtr o = soa.Decode(instance); \ ArtField* f = soa.DecodeField(fid); \ - return f->Get ##fn (o.Decode()) + return f->Get ##fn (o) #define GET_STATIC_PRIMITIVE_FIELD(fn) \ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \ @@ -1275,7 +1280,7 @@ class JNI { ScopedObjectAccess soa(env); \ ObjPtr o = soa.Decode(instance); \ ArtField* f = soa.DecodeField(fid); \ - f->Set ##fn (o.Decode(), value) + f->Set ##fn (o, value) #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \ @@ -2159,13 +2164,13 @@ class JNI { const char* sig = methods[i].signature; const void* fnPtr = methods[i].fnPtr; if (UNLIKELY(name == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Decode(), "method name", i, return_errors); + ReportInvalidJNINativeMethod(soa, c, "method name", i, return_errors); return JNI_ERR; } else if (UNLIKELY(sig == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Decode(), "method signature", i, return_errors); + ReportInvalidJNINativeMethod(soa, c, "method signature", i, return_errors); return JNI_ERR; } else if (UNLIKELY(fnPtr == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Decode(), "native function", i, return_errors); + ReportInvalidJNINativeMethod(soa, c, "native function", i, return_errors); return JNI_ERR; } bool is_fast = false; diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 5a5f71753..8aebd6ed9 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -341,13 +341,13 @@ inline bool Class::Implements(Class* klass) { // Don't forget about primitive types. // Object[] = int[] --> false // -inline bool Class::IsArrayAssignableFromArray(Class* src) { +inline bool Class::IsArrayAssignableFromArray(ObjPtr 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 src) { DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom DCHECK(src->IsArrayClass()) << PrettyClass(src); if (!IsArrayClass()) { @@ -362,8 +362,10 @@ inline bool Class::IsAssignableFromArray(Class* src) { } template -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 @@ inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method, return false; } -inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field, - DexCache* dex_cache, uint32_t field_idx) { - return ResolvedFieldAccessTest(access_to, field, field_idx, dex_cache); +inline bool Class::CanAccessResolvedField(ObjPtr access_to, + ArtField* field, + ObjPtr dex_cache, + uint32_t field_idx) { + return ResolvedFieldAccessTest(access_to.Decode(), + field, + field_idx, + dex_cache.Decode()); } -inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field, +inline bool Class::CheckResolvedFieldAccess(ObjPtr access_to, + ArtField* field, uint32_t field_idx) { - return ResolvedFieldAccessTest(access_to, field, field_idx, nullptr); + return ResolvedFieldAccessTest(access_to.Decode(), field, field_idx, nullptr); } inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method, @@ -469,10 +477,10 @@ inline bool Class::CheckResolvedMethodAccess(Class* access_to, ArtMethod* method nullptr); } -inline bool Class::IsSubClass(Class* klass) { +inline bool Class::IsSubClass(ObjPtr klass) { DCHECK(!IsInterface()) << PrettyClass(this); DCHECK(!IsArrayClass()) << PrettyClass(this); - Class* current = this; + ObjPtr current = this; do { if (current == klass) { return true; @@ -1032,7 +1040,7 @@ inline bool Class::IsArrayClass() { return GetComponentType() != nullptr; } -inline bool Class::IsAssignableFrom(Class* src) { +inline bool Class::IsAssignableFrom(ObjPtr src) { DCHECK(src != nullptr); if (this == src) { // Can always assign to things of the same type. @@ -1113,6 +1121,34 @@ inline void Class::FixupNativePointers(mirror::Class* dest, } } +inline bool Class::CanAccess(ObjPtr that) { + return that->IsPublic() || this->IsInSamePackage(that); +} + + +inline bool Class::CanAccessMember(ObjPtr 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 2e5f53260..40742d273 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -308,9 +308,9 @@ bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& d } } -bool Class::IsInSamePackage(Class* that) { - Class* klass1 = this; - Class* klass2 = that; +bool Class::IsInSamePackage(ObjPtr that) { + ObjPtr klass1 = this; + ObjPtr klass2 = that; if (klass1 == klass2) { return true; } diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 6c1259bf5..d38f235b8 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -611,50 +611,28 @@ class MANAGED Class FINAL : public Object { } // 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 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 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 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 access_to, + ArtField* field, + ObjPtr 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 access_to, ArtField* field, uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); // Can this class access a resolved method? @@ -668,14 +646,14 @@ class MANAGED Class FINAL : public Object { uint32_t method_idx) REQUIRES_SHARED(Locks::mutator_lock_); - bool IsSubClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); + bool IsSubClass(ObjPtr 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 src) REQUIRES_SHARED(Locks::mutator_lock_); template @@ -1309,8 +1287,10 @@ class MANAGED Class FINAL : public Object { void SetVerifyError(Object* klass) REQUIRES_SHARED(Locks::mutator_lock_); template - 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 ResolvedMethodAccessTest(Class* access_to, ArtMethod* resolved_method, @@ -1318,8 +1298,8 @@ class MANAGED Class FINAL : public Object { 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 klass) REQUIRES_SHARED(Locks::mutator_lock_); + bool IsAssignableFromArray(ObjPtr 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 8b0f8ce1f..ec32cb6e3 100644 --- a/runtime/mirror/field-inl.h +++ b/runtime/mirror/field-inl.h @@ -78,6 +78,11 @@ inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field, b return ret.Get(); } +template +void Field::SetDeclaringClass(ObjPtr c) { + SetFieldObject(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 f37856825..c5357c9d3 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 @@ class MANAGED Field : public AccessibleObject { int32_t offset_; template - void SetDeclaringClass(mirror::Class* c) REQUIRES_SHARED(Locks::mutator_lock_) { - SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), c); - } + void SetDeclaringClass(ObjPtr c) REQUIRES_SHARED(Locks::mutator_lock_); template void SetType(mirror::Class* type) REQUIRES_SHARED(Locks::mutator_lock_) { diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index c37deb52b..90b97fd14 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -213,7 +213,7 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val 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(); + ObjPtr field_type = field.GetType(); if (field_type != nullptr) { CHECK(field_type->IsAssignableFrom(new_value->GetClass())); } @@ -230,7 +230,7 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val 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(); + ObjPtr field_type = field.GetType(); 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 40ee3a2e5..a573ae631 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -384,12 +384,12 @@ TEST_F(ObjectTest, StaticFieldFromCode) { ArtField* field = FindFieldFromCode(field_idx, clinit, Thread::Current(), sizeof(HeapReference)); - Object* s0 = field->GetObj(klass); + ObjPtr s0 = field->GetObj(klass); EXPECT_TRUE(s0 != nullptr); Handle char_array(hs.NewHandle(CharArray::Alloc(soa.Self(), 0))); field->SetObj(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(field->GetDeclaringClass(), nullptr); EXPECT_EQ(nullptr, field->GetObj(klass)); @@ -759,7 +759,7 @@ TEST_F(ObjectTest, ObjectPointer) { 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 Y(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); EXPECT_TRUE(!Y.IsNull()); @@ -773,7 +773,7 @@ TEST_F(ObjectTest, ObjectPointer) { 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 @@ TEST_F(ObjectTest, ObjectPointer) { 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 diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index acad2a941..64e5a638a 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -30,6 +30,7 @@ #include "handle_scope-inl.h" #include "mirror/class_loader.h" #include "oat_file_assistant.h" +#include "obj_ptr-inl.h" #include "scoped_thread_state_change-inl.h" #include "thread-inl.h" #include "thread_list.h" @@ -223,7 +224,7 @@ static void AddNext(/*inout*/DexFileAndClassPair* original, } } -static void IterateOverJavaDexFile(mirror::Object* dex_file, +static void IterateOverJavaDexFile(ObjPtr dex_file, ArtField* const cookie_field, std::function fn) REQUIRES_SHARED(Locks::mutator_lock_) { @@ -258,12 +259,12 @@ static void IterateOverPathClassLoader( ArtField* const cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); ArtField* const dex_file_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); - mirror::Object* dex_path_list = + ObjPtr dex_path_list = soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> GetObject(class_loader.Get()); if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. - mirror::Object* dex_elements_obj = + ObjPtr dex_elements_obj = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> GetObject(dex_path_list); // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look @@ -276,7 +277,7 @@ static void IterateOverPathClassLoader( // Should never happen, fall back to java code to throw a NPE. break; } - mirror::Object* dex_file = dex_file_field->GetObject(element); + ObjPtr dex_file = dex_file_field->GetObject(element); IterateOverJavaDexFile(dex_file, cookie_field, fn); } } @@ -360,7 +361,7 @@ static void GetDexFilesFromDexElementsArray( // We support this being dalvik.system.DexPathList$Element and dalvik.system.DexFile. - mirror::Object* dex_file; + ObjPtr dex_file; if (element_class == element->GetClass()) { dex_file = dex_file_field->GetObject(element); } else if (dexfile_class == element->GetClass()) { diff --git a/runtime/obj_ptr.h b/runtime/obj_ptr.h index d5ac33d8b..7c0c9df7d 100644 --- a/runtime/obj_ptr.h +++ b/runtime/obj_ptr.h @@ -88,11 +88,13 @@ class ObjPtr { return Decode() == ptr.Decode(); } - ALWAYS_INLINE bool operator==(const MirrorType* ptr) const REQUIRES_SHARED(Locks::mutator_lock_) { + template + ALWAYS_INLINE bool operator==(const PointerType* ptr) const + REQUIRES_SHARED(Locks::mutator_lock_) { return Decode() == ptr; } - ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) { + ALWAYS_INLINE bool operator==(std::nullptr_t) const { return IsNull(); } @@ -100,16 +102,18 @@ class ObjPtr { return Decode() != ptr.Decode(); } - ALWAYS_INLINE bool operator!=(const MirrorType* ptr) const REQUIRES_SHARED(Locks::mutator_lock_) { + template + ALWAYS_INLINE bool operator!=(const PointerType* ptr) const + REQUIRES_SHARED(Locks::mutator_lock_) { return Decode() != ptr; } - ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) { + ALWAYS_INLINE bool operator!=(std::nullptr_t) const { return !IsNull(); } // Decode unchecked does not check that object pointer is valid. Do not use if you can avoid it. - ALWAYS_INLINE MirrorType* DecodeUnchecked() const REQUIRES_SHARED(Locks::mutator_lock_) { + ALWAYS_INLINE MirrorType* DecodeUnchecked() const { if (kPoison) { return reinterpret_cast( static_cast(static_cast(reference_ << kObjectAlignmentShift))); @@ -133,14 +137,40 @@ class ObjPtr { uintptr_t reference_; }; +template +ALWAYS_INLINE bool operator==(const PointerType* a, const ObjPtr& b) + REQUIRES_SHARED(Locks::mutator_lock_) { + return b == a; +} + +template +ALWAYS_INLINE bool operator==(std::nullptr_t, const ObjPtr& b) { + return b == nullptr; +} + +template +ALWAYS_INLINE bool operator!=(const PointerType* a, const ObjPtr& b) + REQUIRES_SHARED(Locks::mutator_lock_) { + return b != a; +} + +template +ALWAYS_INLINE bool operator!=(std::nullptr_t, const ObjPtr& b) { + return b != nullptr; +} + template static inline ObjPtr MakeObjPtr(MirrorType* ptr) { return ObjPtr(ptr); } +template +static inline ObjPtr MakeObjPtr(ObjPtr ptr) { + return ObjPtr(ptr); +} + template -ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr ptr) - REQUIRES_SHARED(Locks::mutator_lock_); +ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr ptr); } // namespace art diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc index ac348e724..9c42b2ff8 100644 --- a/runtime/openjdkjvmti/transform.cc +++ b/runtime/openjdkjvmti/transform.cc @@ -209,9 +209,9 @@ static bool FindDalvikSystemDexFileAndLoaderForClass( hs.NewHandle(path_list_field->GetObject(h_class_loader.Get()))); CHECK(path_list.Get() != nullptr); CHECK(!self->IsExceptionPending()); - art::Handle> dex_elements_list( - hs.NewHandle(art::down_cast*>( - dex_path_list_element_field->GetObject(path_list.Get())))); + art::Handle> dex_elements_list(hs.NewHandle( + dex_path_list_element_field->GetObject(path_list.Get())-> + AsObjectArray())); CHECK(!self->IsExceptionPending()); CHECK(dex_elements_list.Get() != nullptr); size_t num_elements = dex_elements_list->GetLength(); diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc index 43b0b3d4f..1119ccfc8 100644 --- a/runtime/proxy_test.cc +++ b/runtime/proxy_test.cc @@ -180,7 +180,7 @@ TEST_F(ProxyTest, ProxyFieldHelper) { ArtField* field = &static_fields->At(0); EXPECT_STREQ("interfaces", field->GetName()); EXPECT_STREQ("[Ljava/lang/Class;", field->GetTypeDescriptor()); - EXPECT_EQ(interfacesFieldClass.Get(), field->GetType()); + EXPECT_OBJ_PTR_EQ(MakeObjPtr(interfacesFieldClass.Get()), field->GetType()); std::string temp; EXPECT_STREQ("L$Proxy1234;", field->GetDeclaringClass()->GetDescriptor(&temp)); EXPECT_FALSE(field->IsPrimitiveType()); @@ -189,7 +189,7 @@ TEST_F(ProxyTest, ProxyFieldHelper) { field = &static_fields->At(1); EXPECT_STREQ("throws", field->GetName()); EXPECT_STREQ("[[Ljava/lang/Class;", field->GetTypeDescriptor()); - EXPECT_EQ(throwsFieldClass.Get(), field->GetType()); + EXPECT_OBJ_PTR_EQ(MakeObjPtr(throwsFieldClass.Get()), field->GetType()); EXPECT_STREQ("L$Proxy1234;", field->GetDeclaringClass()->GetDescriptor(&temp)); EXPECT_FALSE(field->IsPrimitiveType()); } @@ -224,10 +224,10 @@ TEST_F(ProxyTest, CheckArtMirrorFieldsOfProxyStaticFields) { ASSERT_TRUE(static_fields1 != nullptr); ASSERT_EQ(2u, static_fields1->size()); - EXPECT_EQ(static_fields0->At(0).GetDeclaringClass(), proxyClass0.Get()); - EXPECT_EQ(static_fields0->At(1).GetDeclaringClass(), proxyClass0.Get()); - EXPECT_EQ(static_fields1->At(0).GetDeclaringClass(), proxyClass1.Get()); - EXPECT_EQ(static_fields1->At(1).GetDeclaringClass(), proxyClass1.Get()); + EXPECT_OBJ_PTR_EQ(static_fields0->At(0).GetDeclaringClass(), MakeObjPtr(proxyClass0.Get())); + EXPECT_OBJ_PTR_EQ(static_fields0->At(1).GetDeclaringClass(), MakeObjPtr(proxyClass0.Get())); + EXPECT_OBJ_PTR_EQ(static_fields1->At(0).GetDeclaringClass(), MakeObjPtr(proxyClass1.Get())); + EXPECT_OBJ_PTR_EQ(static_fields1->At(1).GetDeclaringClass(), MakeObjPtr(proxyClass1.Get())); ASSERT_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize); ASSERT_FALSE(Runtime::Current()->IsActiveTransaction()); diff --git a/runtime/quick/inline_method_analyser.cc b/runtime/quick/inline_method_analyser.cc index dc6f4ebc9..b009b4719 100644 --- a/runtime/quick/inline_method_analyser.cc +++ b/runtime/quick/inline_method_analyser.cc @@ -738,8 +738,8 @@ bool InlineMethodAnalyser::ComputeSpecialAccessorInfo(ArtMethod* method, if (field == nullptr || field->IsStatic()) { return false; } - mirror::Class* method_class = method->GetDeclaringClass(); - mirror::Class* field_class = field->GetDeclaringClass(); + ObjPtr method_class = method->GetDeclaringClass(); + ObjPtr field_class = field->GetDeclaringClass(); if (!method_class->CanAccessResolvedField(field_class, field, dex_cache, field_idx) || (is_put && field->IsFinal() && method_class != field_class)) { return false; diff --git a/runtime/reflection.cc b/runtime/reflection.cc index b663b4c8e..066bc1264 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -244,13 +244,13 @@ class ArgArray { #define DO_FIRST_ARG(match_descriptor, get_fn, append) { \ if (LIKELY(arg != nullptr && arg->GetClass()->DescriptorEquals(match_descriptor))) { \ ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ - append(primitive_field-> get_fn(arg.Decode())); + append(primitive_field-> get_fn(arg)); #define DO_ARG(match_descriptor, get_fn, append) \ } else if (LIKELY(arg != nullptr && \ arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \ ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ - append(primitive_field-> get_fn(arg.Decode())); + append(primitive_field-> get_fn(arg)); #define DO_FAIL(expected) \ } else { \ @@ -801,28 +801,28 @@ static bool UnboxPrimitive(ObjPtr o, ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0); if (klass->DescriptorEquals("Ljava/lang/Boolean;")) { src_class = class_linker->FindPrimitiveClass('Z'); - boxed_value.SetZ(primitive_field->GetBoolean(o.Decode())); + boxed_value.SetZ(primitive_field->GetBoolean(o)); } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) { src_class = class_linker->FindPrimitiveClass('B'); - boxed_value.SetB(primitive_field->GetByte(o.Decode())); + boxed_value.SetB(primitive_field->GetByte(o)); } else if (klass->DescriptorEquals("Ljava/lang/Character;")) { src_class = class_linker->FindPrimitiveClass('C'); - boxed_value.SetC(primitive_field->GetChar(o.Decode())); + boxed_value.SetC(primitive_field->GetChar(o)); } else if (klass->DescriptorEquals("Ljava/lang/Float;")) { src_class = class_linker->FindPrimitiveClass('F'); - boxed_value.SetF(primitive_field->GetFloat(o.Decode())); + boxed_value.SetF(primitive_field->GetFloat(o)); } else if (klass->DescriptorEquals("Ljava/lang/Double;")) { src_class = class_linker->FindPrimitiveClass('D'); - boxed_value.SetD(primitive_field->GetDouble(o.Decode())); + boxed_value.SetD(primitive_field->GetDouble(o)); } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) { src_class = class_linker->FindPrimitiveClass('I'); - boxed_value.SetI(primitive_field->GetInt(o.Decode())); + boxed_value.SetI(primitive_field->GetInt(o)); } else if (klass->DescriptorEquals("Ljava/lang/Long;")) { src_class = class_linker->FindPrimitiveClass('J'); - boxed_value.SetJ(primitive_field->GetLong(o.Decode())); + boxed_value.SetJ(primitive_field->GetLong(o)); } else if (klass->DescriptorEquals("Ljava/lang/Short;")) { src_class = class_linker->FindPrimitiveClass('S'); - boxed_value.SetS(primitive_field->GetShort(o.Decode())); + boxed_value.SetS(primitive_field->GetShort(o)); } else { std::string temp; ThrowIllegalArgumentException( @@ -888,13 +888,13 @@ bool VerifyAccess(ObjPtr obj, } if ((access_flags & kAccProtected) != 0) { if (obj != nullptr && !obj->InstanceOf(calling_class) && - !declaring_class->IsInSamePackage(calling_class.Decode())) { + !declaring_class->IsInSamePackage(calling_class)) { return false; - } else if (declaring_class->IsAssignableFrom(calling_class.Decode())) { + } else if (declaring_class->IsAssignableFrom(calling_class)) { return true; } } - return declaring_class->IsInSamePackage(calling_class.Decode()); + return declaring_class->IsInSamePackage(calling_class); } void InvalidReceiverError(ObjPtr o, ObjPtr c) { diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h index bb6eb790a..d75a788e9 100644 --- a/runtime/thread-inl.h +++ b/runtime/thread-inl.h @@ -175,9 +175,7 @@ inline void Thread::PassActiveSuspendBarriers() { inline void Thread::TransitionFromRunnableToSuspended(ThreadState new_state) { AssertThreadSuspensionIsAllowable(); - if (kIsDebugBuild) { - PoisonObjectPointers(); - } + PoisonObjectPointersIfDebug(); DCHECK_EQ(this, Thread::Current()); // Change to non-runnable state, thereby appearing suspended to the system. TransitionToSuspendedAndRunCheckpoints(new_state); diff --git a/runtime/thread.cc b/runtime/thread.cc index ec1bb3fa1..b8c709652 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -563,8 +563,8 @@ void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_siz ScopedObjectAccess soa(env); ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); - mirror::String* java_name = reinterpret_cast(f->GetObject( - soa.Decode(java_peer).Decode())); + ObjPtr java_name = + f->GetObject(soa.Decode(java_peer))->AsString(); std::string thread_name; if (java_name != nullptr) { thread_name = java_name->ToModifiedUtf8(); @@ -845,11 +845,9 @@ void Thread::InitPeer(ScopedObjectAccess& soa, jboolean thread_is_daemon, jobjec soa.DecodeField(WellKnownClasses::java_lang_Thread_daemon)-> SetBoolean(tlsPtr_.opeer, thread_is_daemon); soa.DecodeField(WellKnownClasses::java_lang_Thread_group)-> - SetObject(tlsPtr_.opeer, - soa.Decode(thread_group).Decode()); + SetObject(tlsPtr_.opeer, soa.Decode(thread_group)); soa.DecodeField(WellKnownClasses::java_lang_Thread_name)-> - SetObject(tlsPtr_.opeer, - soa.Decode(thread_name).Decode()); + SetObject(tlsPtr_.opeer, soa.Decode(thread_name)); soa.DecodeField(WellKnownClasses::java_lang_Thread_priority)-> SetInt(tlsPtr_.opeer, thread_priority); } @@ -948,8 +946,11 @@ void Thread::Dump(std::ostream& os, bool dump_native_stack, BacktraceMap* backtr mirror::String* Thread::GetThreadName(const ScopedObjectAccessAlreadyRunnable& soa) const { ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); - return (tlsPtr_.opeer != nullptr) ? - reinterpret_cast(f->GetObject(tlsPtr_.opeer)) : nullptr; + if (tlsPtr_.opeer == nullptr) { + return nullptr; + } + ObjPtr name = f->GetObject(tlsPtr_.opeer); + return name == nullptr ? nullptr : name->AsString(); } void Thread::GetThreadName(std::string& name) const { @@ -1220,14 +1221,14 @@ void Thread::DumpState(std::ostream& os, const Thread* thread, pid_t tid) { is_daemon = soa.DecodeField(WellKnownClasses::java_lang_Thread_daemon) ->GetBoolean(thread->tlsPtr_.opeer); - mirror::Object* thread_group = + ObjPtr thread_group = soa.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(thread->tlsPtr_.opeer); if (thread_group != nullptr) { ArtField* group_name_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); - mirror::String* group_name_string = - reinterpret_cast(group_name_field->GetObject(thread_group)); + ObjPtr group_name_string = + group_name_field->GetObject(thread_group)->AsString(); group_name = (group_name_string != nullptr) ? group_name_string->ToModifiedUtf8() : ""; } } else { @@ -1711,7 +1712,7 @@ void Thread::Destroy() { // Thread.join() is implemented as an Object.wait() on the Thread.lock object. Signal anyone // who is waiting. - mirror::Object* lock = + ObjPtr lock = soa.DecodeField(WellKnownClasses::java_lang_Thread_lock)->GetObject(tlsPtr_.opeer); // (This conditional is only needed for tests, where Thread.lock won't have been set.) if (lock != nullptr) { @@ -1803,7 +1804,7 @@ void Thread::HandleUncaughtExceptions(ScopedObjectAccess& soa) { void Thread::RemoveFromThreadGroup(ScopedObjectAccess& soa) { // this.group.removeThread(this); // group can be null if we're in the compiler or a test. - mirror::Object* ogroup = soa.DecodeField(WellKnownClasses::java_lang_Thread_group) + ObjPtr ogroup = soa.DecodeField(WellKnownClasses::java_lang_Thread_group) ->GetObject(tlsPtr_.opeer); if (ogroup != nullptr) { ScopedLocalRef group(soa.Env(), soa.AddLocalReference(ogroup)); diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 87b6dc3a8..50466edc1 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -4563,9 +4563,11 @@ ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_id return nullptr; } else { std::string temp; - mirror::Class* klass = field->GetDeclaringClass(); + ObjPtr klass = field->GetDeclaringClass(); const RegType& field_klass = - FromClass(klass->GetDescriptor(&temp), klass, klass->CannotBeAssignedFromOtherTypes()); + FromClass(klass->GetDescriptor(&temp), + klass.Decode(), + klass->CannotBeAssignedFromOtherTypes()); if (obj_type.IsUninitializedTypes()) { // Field accesses through uninitialized references are only allowable for constructors where // the field is declared in this class. @@ -4662,10 +4664,11 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& } } - mirror::Class* field_type_class = + ObjPtr field_type_class = can_load_classes_ ? field->GetType() : field->GetType(); if (field_type_class != nullptr) { - field_type = &FromClass(field->GetTypeDescriptor(), field_type_class, + field_type = &FromClass(field->GetTypeDescriptor(), + field_type_class.Decode(), field_type_class->CannotBeAssignedFromOtherTypes()); } else { DCHECK(!can_load_classes_ || self_->IsExceptionPending()); @@ -4785,12 +4788,12 @@ void MethodVerifier::VerifyQuickFieldAccess(const Instruction* inst, const RegTy // Get the field type. const RegType* field_type; { - mirror::Class* field_type_class = can_load_classes_ ? field->GetType() : + ObjPtr field_type_class = can_load_classes_ ? field->GetType() : field->GetType(); if (field_type_class != nullptr) { field_type = &FromClass(field->GetTypeDescriptor(), - field_type_class, + field_type_class.Decode(), field_type_class->CannotBeAssignedFromOtherTypes()); } else { Thread* self = Thread::Current(); diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h index d93aaa193..10f1be510 100644 --- a/runtime/verifier/reg_type-inl.h +++ b/runtime/verifier/reg_type-inl.h @@ -44,7 +44,7 @@ inline bool RegType::CanAccess(const RegType& other) const { } } -inline bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const { +inline bool RegType::CanAccessMember(ObjPtr klass, uint32_t access_flags) const { if ((access_flags & kAccPublic) != 0) { return true; } diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h index 9170bb1a6..472381dd9 100644 --- a/runtime/verifier/reg_type.h +++ b/runtime/verifier/reg_type.h @@ -29,6 +29,7 @@ #include "base/stringpiece.h" #include "gc_root.h" #include "handle_scope.h" +#include "obj_ptr.h" #include "object_callbacks.h" #include "primitive.h" @@ -205,7 +206,7 @@ class RegType { REQUIRES_SHARED(Locks::mutator_lock_); // Can this type access a member with the given properties? - bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const + bool CanAccessMember(ObjPtr klass, uint32_t access_flags) const REQUIRES_SHARED(Locks::mutator_lock_); // Can this type be assigned by src? diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc index 350c83871..3e1958f2c 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -19,6 +19,7 @@ #include "compiler_callbacks.h" #include "leb128.h" #include "mirror/class-inl.h" +#include "obj_ptr-inl.h" #include "runtime.h" namespace art { @@ -107,10 +108,10 @@ std::string VerifierDeps::GetStringFromId(const DexFile& dex_file, uint32_t stri } } -bool VerifierDeps::IsInClassPath(mirror::Class* klass) { +bool VerifierDeps::IsInClassPath(ObjPtr klass) { DCHECK(klass != nullptr); - mirror::DexCache* dex_cache = klass->GetDexCache(); + ObjPtr dex_cache = klass->GetDexCache(); if (dex_cache == nullptr) { // This is a synthesized class, in this case always an array. They are not // defined in the compiled DEX files and therefore are part of the classpath. diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index dc8dfaf2f..3223f6f7b 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -26,6 +26,7 @@ #include "base/array_ref.h" #include "base/mutex.h" #include "method_resolution_kind.h" +#include "obj_ptr.h" #include "os.h" namespace art { @@ -176,7 +177,7 @@ class VerifierDeps { // Returns true if `klass` is null or not defined in any of dex files which // were reported as being compiled. - bool IsInClassPath(mirror::Class* klass) + bool IsInClassPath(ObjPtr klass) REQUIRES_SHARED(Locks::mutator_lock_); // Returns the index of `str`. If it is defined in `dex_file_`, this is the dex