diff options
author | Hiroshi Yamauchi <yamauchi@google.com> | 2015-05-13 21:14:22 -0700 |
---|---|---|
committer | Hiroshi Yamauchi <yamauchi@google.com> | 2015-05-14 12:02:03 -0700 |
commit | 375a29a824207fb2187bc3d31bfaae2d8283b3a2 (patch) | |
tree | f8159bbd7c556d9b54a5782346cea0d1f0861926 | |
parent | 3b0ee6f06b6643e2a601283e779ba5d574fe1fda (diff) | |
download | art-375a29a824207fb2187bc3d31bfaae2d8283b3a2.zip art-375a29a824207fb2187bc3d31bfaae2d8283b3a2.tar.gz art-375a29a824207fb2187bc3d31bfaae2d8283b3a2.tar.bz2 |
Print field info on mark sweep invalid ref crash.
(cherry pick commit eb2baaf20d9059c0fc38141780ec05bea0486c40)
Bug: 20557050
Change-Id: I3abb7a44e3b7ed3256653824fd1705aac5f7d72c
-rw-r--r-- | runtime/art_field.cc | 11 | ||||
-rw-r--r-- | runtime/art_field.h | 3 | ||||
-rw-r--r-- | runtime/gc/accounting/heap_bitmap.h | 2 | ||||
-rw-r--r-- | runtime/gc/collector/mark_sweep.cc | 26 | ||||
-rw-r--r-- | runtime/gc/collector/mark_sweep.h | 6 | ||||
-rw-r--r-- | runtime/mirror/object.cc | 5 | ||||
-rw-r--r-- | runtime/mirror/object.h | 2 |
7 files changed, 46 insertions, 9 deletions
diff --git a/runtime/art_field.cc b/runtime/art_field.cc index 2aed440..47d5a76 100644 --- a/runtime/art_field.cc +++ b/runtime/art_field.cc @@ -63,6 +63,17 @@ ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t f FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset) : nullptr; } +ArtField* ArtField::FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) { + DCHECK(klass != nullptr); + auto* static_fields = klass->GetSFields(); + for (size_t i = 0, count = klass->NumStaticFields(); i < count; ++i) { + if (static_fields[i].GetOffset().Uint32Value() == field_offset) { + return &static_fields[i]; + } + } + return nullptr; +} + mirror::Class* ArtField::ProxyFindSystemClass(const char* descriptor) { DCHECK(GetDeclaringClass()->IsProxyClass()); return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), descriptor); diff --git a/runtime/art_field.h b/runtime/art_field.h index c0620bf..9d3dbd9 100644 --- a/runtime/art_field.h +++ b/runtime/art_field.h @@ -161,6 +161,9 @@ class ArtField { // Returns an instance field with this offset in the given class or null if not found. static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Returns a static field with this offset in the given class or null if not found. + static ArtField* FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/gc/accounting/heap_bitmap.h b/runtime/gc/accounting/heap_bitmap.h index 245e074..1648aef 100644 --- a/runtime/gc/accounting/heap_bitmap.h +++ b/runtime/gc/accounting/heap_bitmap.h @@ -39,9 +39,11 @@ class HeapBitmap { void Clear(const mirror::Object* obj) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); template<typename LargeObjectSetVisitor> bool Set(const mirror::Object* obj, const LargeObjectSetVisitor& visitor) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) ALWAYS_INLINE; template<typename LargeObjectSetVisitor> bool AtomicTestAndSet(const mirror::Object* obj, const LargeObjectSetVisitor& visitor) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) ALWAYS_INLINE; ContinuousSpaceBitmap* GetContinuousSpaceBitmap(const mirror::Object* obj) const; LargeObjectBitmap* GetLargeObjectBitmap(const mirror::Object* obj) const; diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index 55a8411..53e56da 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -368,10 +368,13 @@ bool MarkSweep::HeapReferenceMarkedCallback(mirror::HeapReference<mirror::Object class MarkSweepMarkObjectSlowPath { public: - explicit MarkSweepMarkObjectSlowPath(MarkSweep* mark_sweep) : mark_sweep_(mark_sweep) { + explicit MarkSweepMarkObjectSlowPath(MarkSweep* mark_sweep, Object* holder = nullptr, + MemberOffset offset = MemberOffset(0)) + : mark_sweep_(mark_sweep), holder_(holder), offset_(offset) { } - void operator()(const Object* obj) const ALWAYS_INLINE { + void operator()(const Object* obj) const ALWAYS_INLINE + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (kProfileLargeObjects) { // TODO: Differentiate between marking and testing somehow. ++mark_sweep_->large_object_test_; @@ -384,6 +387,13 @@ class MarkSweepMarkObjectSlowPath { LOG(INTERNAL_FATAL) << "Tried to mark " << obj << " not contained by any spaces"; LOG(INTERNAL_FATAL) << "Attempting see if it's a bad root"; mark_sweep_->VerifyRoots(); + if (holder_ != nullptr) { + ArtField* field = holder_->FindFieldByOffset(offset_); + LOG(INTERNAL_FATAL) << "Field info: holder=" << holder_ + << " holder_type=" << PrettyTypeOf(holder_) + << " offset=" << offset_.Uint32Value() + << " field=" << (field != nullptr ? field->GetName() : "nullptr"); + } PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL); MemMap::DumpMaps(LOG(INTERNAL_FATAL), true); LOG(FATAL) << "Can't mark invalid object"; @@ -392,9 +402,11 @@ class MarkSweepMarkObjectSlowPath { private: MarkSweep* const mark_sweep_; + mirror::Object* const holder_; + MemberOffset offset_; }; -inline void MarkSweep::MarkObjectNonNull(Object* obj) { +inline void MarkSweep::MarkObjectNonNull(Object* obj, Object* holder, MemberOffset offset) { DCHECK(obj != nullptr); if (kUseBakerOrBrooksReadBarrier) { // Verify all the objects have the correct pointer installed. @@ -416,7 +428,7 @@ inline void MarkSweep::MarkObjectNonNull(Object* obj) { if (kCountMarkedObjects) { ++mark_slowpath_count_; } - MarkSweepMarkObjectSlowPath visitor(this); + MarkSweepMarkObjectSlowPath visitor(this, holder, offset); // TODO: We already know that the object is not in the current_space_bitmap_ but MarkBitmap::Set // will check again. if (!mark_bitmap_->Set(obj, visitor)) { @@ -456,9 +468,9 @@ inline bool MarkSweep::MarkObjectParallel(const Object* obj) { } // Used to mark objects when processing the mark stack. If an object is null, it is not marked. -inline void MarkSweep::MarkObject(Object* obj) { +inline void MarkSweep::MarkObject(Object* obj, Object* holder, MemberOffset offset) { if (obj != nullptr) { - MarkObjectNonNull(obj); + MarkObjectNonNull(obj, holder, offset); } else if (kCountMarkedObjects) { ++mark_null_count_; } @@ -1209,7 +1221,7 @@ class MarkObjectVisitor { Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current()); } - mark_sweep_->MarkObject(obj->GetFieldObject<mirror::Object>(offset)); + mark_sweep_->MarkObject(obj->GetFieldObject<mirror::Object>(offset), obj, offset); } private: diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h index 7e1af7b..d29d87a 100644 --- a/runtime/gc/collector/mark_sweep.h +++ b/runtime/gc/collector/mark_sweep.h @@ -199,7 +199,8 @@ class MarkSweep : public GarbageCollector { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Marks an object. - void MarkObject(mirror::Object* obj) + void MarkObject(mirror::Object* obj, mirror::Object* holder = nullptr, + MemberOffset offset = MemberOffset(0)) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); @@ -222,7 +223,8 @@ class MarkSweep : public GarbageCollector { static void VerifyImageRootVisitor(mirror::Object* root, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_); - void MarkObjectNonNull(mirror::Object* obj) + void MarkObjectNonNull(mirror::Object* obj, mirror::Object* holder = nullptr, + MemberOffset offset = MemberOffset(0)) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index 5dac985..f9740bb 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -244,5 +244,10 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val UNREACHABLE(); } +ArtField* Object::FindFieldByOffset(MemberOffset offset) { + return IsClass() ? ArtField::FindStaticFieldWithOffset(AsClass(), offset.Uint32Value()) + : ArtField::FindInstanceFieldWithOffset(GetClass(), offset.Uint32Value()); +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h index f2d879f..5afe99f 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -439,6 +439,8 @@ class MANAGED LOCKABLE Object { void VisitReferences(const Visitor& visitor, const JavaLangRefVisitor& ref_visitor) NO_THREAD_SAFETY_ANALYSIS; + ArtField* FindFieldByOffset(MemberOffset offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Used by object_test. static void SetHashCodeSeed(uint32_t new_seed); // Generate an identity hash code. Public for object test. |