summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-08-18 13:54:21 -0700
committerMathieu Chartier <mathieuc@google.com>2015-08-18 16:11:21 -0700
commit059ef3ddb2088f926ac452889e0953fdcd646a5e (patch)
tree36067457d7e4aba11be908ddd235734d29b7c4f2 /runtime
parentf71ad9ede9ae322a897e8fe407208dc35c5dee65 (diff)
downloadart-059ef3ddb2088f926ac452889e0953fdcd646a5e.tar.gz
art-059ef3ddb2088f926ac452889e0953fdcd646a5e.tar.bz2
art-059ef3ddb2088f926ac452889e0953fdcd646a5e.zip
Always visit object class from VisitReferences
We don't want to unload classes which have instances. Slight increase in CMS GC time from ~6.5s to ~7.3s on EvaluateAndApplyChanges. Bug: 22720414 Change-Id: I467ff9c9d55163d2a90b999aef3bdd7b3f648bac
Diffstat (limited to 'runtime')
-rw-r--r--runtime/gc/accounting/mod_union_table.cc6
-rw-r--r--runtime/gc/accounting/remembered_set.cc2
-rw-r--r--runtime/gc/collector/concurrent_copying.cc6
-rw-r--r--runtime/gc/collector/mark_compact.cc4
-rw-r--r--runtime/gc/collector/mark_sweep-inl.h2
-rw-r--r--runtime/gc/collector/semi_space.cc4
-rw-r--r--runtime/gc/heap.cc6
-rw-r--r--runtime/hprof/hprof.cc2
-rw-r--r--runtime/mirror/class-inl.h6
-rw-r--r--runtime/mirror/class.cc4
-rw-r--r--runtime/mirror/class.h9
-rw-r--r--runtime/mirror/class_loader-inl.h4
-rw-r--r--runtime/mirror/class_loader.h6
-rw-r--r--runtime/mirror/object-inl.h33
-rw-r--r--runtime/mirror/object.cc2
-rw-r--r--runtime/mirror/object.h11
-rw-r--r--runtime/mirror/object_array-inl.h5
-rw-r--r--runtime/mirror/object_array.h9
18 files changed, 58 insertions, 63 deletions
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index dd9e2d1272..5151819d96 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -153,7 +153,7 @@ class ModUnionScanImageRootVisitor {
DCHECK(root != nullptr);
ModUnionUpdateObjectReferencesVisitor ref_visitor(visitor_, from_space_, immune_space_,
contains_reference_to_other_space_);
- root->VisitReferences<kMovingClasses>(ref_visitor, VoidFunctor());
+ root->VisitReferences(ref_visitor, VoidFunctor());
}
private:
@@ -237,7 +237,7 @@ class ModUnionReferenceVisitor {
visitor_,
references_,
has_target_reference_);
- obj->VisitReferences<kMovingClasses>(visitor, VoidFunctor());
+ obj->VisitReferences(visitor, VoidFunctor());
}
private:
@@ -304,7 +304,7 @@ class ModUnionCheckReferences {
void operator()(Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
Locks::heap_bitmap_lock_->AssertSharedHeld(Thread::Current());
CheckReferenceVisitor visitor(mod_union_table_, references_);
- obj->VisitReferences<kMovingClasses>(visitor, VoidFunctor());
+ obj->VisitReferences(visitor, VoidFunctor());
}
private:
diff --git a/runtime/gc/accounting/remembered_set.cc b/runtime/gc/accounting/remembered_set.cc
index b9f24f348f..277d319035 100644
--- a/runtime/gc/accounting/remembered_set.cc
+++ b/runtime/gc/accounting/remembered_set.cc
@@ -120,7 +120,7 @@ class RememberedSetObjectVisitor {
SHARED_REQUIRES(Locks::mutator_lock_) {
RememberedSetReferenceVisitor visitor(target_space_, contains_reference_to_target_space_,
collector_);
- obj->VisitReferences<kMovingClasses>(visitor, visitor);
+ obj->VisitReferences(visitor, visitor);
}
private:
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 220c06ee5a..263e67879b 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -683,7 +683,7 @@ class ConcurrentCopyingVerifyNoFromSpaceRefsObjectVisitor {
space::RegionSpace* region_space = collector->RegionSpace();
CHECK(!region_space->IsInFromSpace(obj)) << "Scanning object " << obj << " in from space";
ConcurrentCopyingVerifyNoFromSpaceRefsFieldVisitor visitor(collector);
- obj->VisitReferences<true>(visitor, visitor);
+ obj->VisitReferences(visitor, visitor);
if (kUseBakerReadBarrier) {
if (collector->RegionSpace()->IsInToSpace(obj)) {
CHECK(obj->GetReadBarrierPointer() == nullptr)
@@ -808,7 +808,7 @@ class ConcurrentCopyingAssertToSpaceInvariantObjectVisitor {
CHECK(!region_space->IsInFromSpace(obj)) << "Scanning object " << obj << " in from space";
collector->AssertToSpaceInvariant(nullptr, MemberOffset(0), obj);
ConcurrentCopyingAssertToSpaceInvariantFieldVisitor visitor(collector);
- obj->VisitReferences<true>(visitor, visitor);
+ obj->VisitReferences(visitor, visitor);
}
private:
@@ -1546,7 +1546,7 @@ class ConcurrentCopyingRefFieldsVisitor {
void ConcurrentCopying::Scan(mirror::Object* to_ref) {
DCHECK(!region_space_->IsInFromSpace(to_ref));
ConcurrentCopyingRefFieldsVisitor visitor(this);
- to_ref->VisitReferences<true>(visitor, visitor);
+ to_ref->VisitReferences(visitor, visitor);
}
// Process a field.
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index 94ffe6ec79..60f833b349 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -457,7 +457,7 @@ class UpdateReferenceVisitor {
void MarkCompact::UpdateObjectReferences(mirror::Object* obj) {
UpdateReferenceVisitor visitor(this);
- obj->VisitReferences<kMovingClasses>(visitor, visitor);
+ obj->VisitReferences(visitor, visitor);
}
inline mirror::Object* MarkCompact::GetMarkedForwardAddress(mirror::Object* obj) {
@@ -608,7 +608,7 @@ class MarkCompactMarkObjectVisitor {
// Visit all of the references of an object and update.
void MarkCompact::ScanObject(mirror::Object* obj) {
MarkCompactMarkObjectVisitor visitor(this);
- obj->VisitReferences<kMovingClasses>(visitor, visitor);
+ obj->VisitReferences(visitor, visitor);
}
// Scan anything that's on the mark stack.
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index 4e3845e5d6..a3cc83132f 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -32,7 +32,7 @@ template<typename MarkVisitor, typename ReferenceVisitor>
inline void MarkSweep::ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor,
const ReferenceVisitor& ref_visitor) {
DCHECK(IsMarked(obj)) << "Scanning unmarked object " << obj << "\n" << heap_->DumpSpaces();
- obj->VisitReferences<false>(visitor, ref_visitor);
+ obj->VisitReferences(visitor, ref_visitor);
if (kCountScannedTypes) {
mirror::Class* klass = obj->GetClass<kVerifyNone>();
if (UNLIKELY(klass == mirror::Class::GetJavaLangClass())) {
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index fc2a801b7f..a355d406d9 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -320,7 +320,7 @@ class SemiSpaceVerifyNoFromSpaceReferencesVisitor {
void SemiSpace::VerifyNoFromSpaceReferences(Object* obj) {
DCHECK(!from_space_->HasAddress(obj)) << "Scanning object " << obj << " in from space";
SemiSpaceVerifyNoFromSpaceReferencesVisitor visitor(from_space_);
- obj->VisitReferences<kMovingClasses>(visitor, VoidFunctor());
+ obj->VisitReferences(visitor, VoidFunctor());
}
class SemiSpaceVerifyNoFromSpaceReferencesObjectVisitor {
@@ -722,7 +722,7 @@ class SemiSpaceMarkObjectVisitor {
void SemiSpace::ScanObject(Object* obj) {
DCHECK(!from_space_->HasAddress(obj)) << "Scanning object " << obj << " in from space";
SemiSpaceMarkObjectVisitor visitor(this);
- obj->VisitReferences<kMovingClasses>(visitor, visitor);
+ obj->VisitReferences(visitor, visitor);
}
// Scan anything that's on the mark stack.
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index e56351f553..d7f918b4ff 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1795,7 +1795,7 @@ class ReferringObjectsFinder {
// TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for
// annotalysis on visitors.
void operator()(mirror::Object* o) const NO_THREAD_SAFETY_ANALYSIS {
- o->VisitReferences<true>(*this, VoidFunctor());
+ o->VisitReferences(*this, VoidFunctor());
}
// For Object::VisitReferences.
@@ -2788,7 +2788,7 @@ class VerifyObjectVisitor {
// be live or else how did we find it in the live bitmap?
VerifyReferenceVisitor visitor(heap_, fail_count_, verify_referent_);
// The class doesn't count as a reference but we should verify it anyways.
- obj->VisitReferences<true>(visitor, visitor);
+ obj->VisitReferences(visitor, visitor);
}
static void VisitCallback(mirror::Object* obj, void* arg)
@@ -2969,7 +2969,7 @@ class VerifyLiveStackReferences {
void operator()(mirror::Object* obj) const
SHARED_REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
VerifyReferenceCardVisitor visitor(heap_, const_cast<bool*>(&failed_));
- obj->VisitReferences<true>(visitor, VoidFunctor());
+ obj->VisitReferences(visitor, VoidFunctor());
}
bool Failed() const {
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 713797fc3d..a9a236fa69 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -1063,7 +1063,7 @@ void Hprof::DumpHeapObject(mirror::Object* obj) {
}
GcRootVisitor visitor(this);
- obj->VisitReferences<true>(visitor, VoidFunctor());
+ obj->VisitReferences(visitor, VoidFunctor());
gc::Heap* const heap = Runtime::Current()->GetHeap();
const gc::space::ContinuousSpace* const space = heap->FindContinuousSpaceFromObject(obj, true);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index ac9cb09731..cd678f670b 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -669,9 +669,9 @@ inline uint32_t Class::ComputeClassSize(bool has_embedded_tables,
return size;
}
-template <bool kVisitClass, typename Visitor>
+template <typename Visitor>
inline void Class::VisitReferences(mirror::Class* klass, const Visitor& visitor) {
- VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
+ VisitInstanceFieldsReferences(klass, visitor);
// Right after a class is allocated, but not yet loaded
// (kStatusNotReady, see ClassLinker::LoadClass()), GC may find it
// and scan it. IsTemp() may call Class::GetAccessFlags() but may
@@ -683,7 +683,7 @@ inline void Class::VisitReferences(mirror::Class* klass, const Visitor& visitor)
// Temp classes don't ever populate imt/vtable or static fields and they are not even
// allocated with the right size for those. Also, unresolved classes don't have fields
// linked yet.
- VisitStaticFieldsReferences<kVisitClass>(this, visitor);
+ VisitStaticFieldsReferences(this, visitor);
}
// Since this class is reachable, we must also visit the associated roots when we scan it.
VisitNativeRoots(visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index f20cc6ea5c..055b3e5110 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -872,8 +872,8 @@ class CopyClassVisitor {
h_new_class_obj->SetClassSize(new_length_);
// Visit all of the references to make sure there is no from space references in the native
// roots.
- h_new_class_obj->VisitReferences<true>(h_new_class_obj->GetClass(),
- ReadBarrierOnNativeRootsVisitor());
+ static_cast<mirror::Object*>(h_new_class_obj.Get())->VisitReferences(
+ ReadBarrierOnNativeRootsVisitor(), VoidFunctor());
}
private:
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index dc60a380e3..3f375be9ca 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1021,10 +1021,6 @@ class MANAGED Class FINAL : public Object {
void SetPreverifiedFlagOnAllMethods(size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
- template <bool kVisitClass, typename Visitor>
- void VisitReferences(mirror::Class* klass, const Visitor& visitor)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
// Get the descriptor of the class. In a few cases a std::string is required, rather than
// always create one the storage argument is populated and its internal c_str() returned. We do
// this to avoid memory allocation in the common case.
@@ -1153,6 +1149,10 @@ class MANAGED Class FINAL : public Object {
static MemberOffset EmbeddedImTableOffset(size_t pointer_size);
static MemberOffset EmbeddedVTableOffset(size_t pointer_size);
+ template <typename Visitor>
+ void VisitReferences(mirror::Class* klass, const Visitor& visitor)
+ SHARED_REQUIRES(Locks::mutator_lock_);
+
// Defining class loader, or null for the "bootstrap" system loader.
HeapReference<ClassLoader> class_loader_;
@@ -1279,6 +1279,7 @@ class MANAGED Class FINAL : public Object {
static GcRoot<Class> java_lang_Class_;
friend struct art::ClassOffsets; // for verifying offset information
+ friend class Object; // For VisitReferences
DISALLOW_IMPLICIT_CONSTRUCTORS(Class);
};
diff --git a/runtime/mirror/class_loader-inl.h b/runtime/mirror/class_loader-inl.h
index 35f3664fbf..e22ddd7e90 100644
--- a/runtime/mirror/class_loader-inl.h
+++ b/runtime/mirror/class_loader-inl.h
@@ -25,10 +25,10 @@
namespace art {
namespace mirror {
-template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor>
+template <VerifyObjectFlags kVerifyFlags, typename Visitor>
inline void ClassLoader::VisitReferences(mirror::Class* klass, const Visitor& visitor) {
// Visit instance fields first.
- VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
+ VisitInstanceFieldsReferences(klass, visitor);
// Visit classes loaded after.
ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
ClassTable* const class_table = GetClassTable();
diff --git a/runtime/mirror/class_loader.h b/runtime/mirror/class_loader.h
index 21c652a941..f27b6155ce 100644
--- a/runtime/mirror/class_loader.h
+++ b/runtime/mirror/class_loader.h
@@ -46,14 +46,15 @@ class MANAGED ClassLoader : public Object {
SetField64<false>(OFFSET_OF_OBJECT_MEMBER(ClassLoader, class_table_),
reinterpret_cast<uint64_t>(class_table));
}
+
+ private:
// Visit instance fields of the class loader as well as its associated classes.
// Null class loader is handled by ClassLinker::VisitClassRoots.
- template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor>
+ template <VerifyObjectFlags kVerifyFlags, typename Visitor>
void VisitReferences(mirror::Class* klass, const Visitor& visitor)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!Locks::classlinker_classes_lock_);
- private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
HeapReference<Object> packages_;
HeapReference<ClassLoader> parent_;
@@ -63,6 +64,7 @@ class MANAGED ClassLoader : public Object {
uint64_t class_table_;
friend struct art::ClassLoaderOffsets; // for verifying offset information
+ friend class Object; // For VisitReferences
DISALLOW_IMPLICIT_CONSTRUCTORS(ClassLoader);
};
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 7b1660ba7e..586ae30d19 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -942,13 +942,10 @@ inline bool Object::CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrie
return success;
}
-template<bool kVisitClass, bool kIsStatic, typename Visitor>
+template<bool kIsStatic, typename Visitor>
inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
// Instance fields and not the slow-path.
- if (kVisitClass) {
- visitor(this, ClassOffset(), kIsStatic);
- }
uint32_t field_offset = mirror::kObjectHeaderSize;
while (ref_offsets != 0) {
if ((ref_offsets & 1) != 0) {
@@ -974,9 +971,9 @@ inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& v
? klass->GetFirstReferenceStaticFieldOffset(
Runtime::Current()->GetClassLinker()->GetImagePointerSize())
: klass->GetFirstReferenceInstanceFieldOffset();
- for (size_t i = 0; i < num_reference_fields; ++i) {
+ for (size_t i = 0u; i < num_reference_fields; ++i) {
// TODO: Do a simpler check?
- if (kVisitClass || field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
+ if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
visitor(this, field_offset, kIsStatic);
}
field_offset = MemberOffset(field_offset.Uint32Value() +
@@ -986,19 +983,17 @@ inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& v
}
}
-template<bool kVisitClass, typename Visitor>
+template<typename Visitor>
inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
- VisitFieldsReferences<kVisitClass, false>(
- klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
+ VisitFieldsReferences<false>(klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
}
-template<bool kVisitClass, typename Visitor>
+template<typename Visitor>
inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
DCHECK(!klass->IsTemp());
- klass->VisitFieldsReferences<kVisitClass, true>(0, visitor);
+ klass->VisitFieldsReferences<true>(0, visitor);
}
-
template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsClassLoader() {
return GetClass<kVerifyFlags>()->IsClassLoaderClass();
@@ -1010,25 +1005,23 @@ inline mirror::ClassLoader* Object::AsClassLoader() {
return down_cast<mirror::ClassLoader*>(this);
}
-template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,
- typename JavaLangRefVisitor>
+template <VerifyObjectFlags kVerifyFlags, typename Visitor, typename JavaLangRefVisitor>
inline void Object::VisitReferences(const Visitor& visitor,
const JavaLangRefVisitor& ref_visitor) {
mirror::Class* klass = GetClass<kVerifyFlags>();
+ visitor(this, ClassOffset(), false);
if (klass == Class::GetJavaLangClass()) {
- AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor);
+ AsClass<kVerifyNone>()->VisitReferences(klass, visitor);
} else if (klass->IsArrayClass() || klass->IsStringClass()) {
if (klass->IsObjectArrayClass<kVerifyNone>()) {
- AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor);
- } else if (kVisitClass) {
- visitor(this, ClassOffset(), false);
+ AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences(visitor);
}
} else if (klass->IsClassLoaderClass()) {
mirror::ClassLoader* class_loader = AsClassLoader<kVerifyFlags>();
- class_loader->VisitReferences<kVisitClass, kVerifyFlags>(klass, visitor);
+ class_loader->VisitReferences<kVerifyFlags>(klass, visitor);
} else {
DCHECK(!klass->IsVariableSize());
- VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
+ VisitInstanceFieldsReferences(klass, visitor);
if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) {
ref_visitor(klass, AsReference());
}
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index df680b5ba5..4d941302f9 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -85,7 +85,7 @@ Object* Object::CopyObject(Thread* self, mirror::Object* dest, mirror::Object* s
// object above, copy references fields one by one again with a
// RB. TODO: Optimize this later?
CopyReferenceFieldsWithReadBarrierVisitor visitor(dest);
- src->VisitReferences<true>(visitor, visitor);
+ src->VisitReferences(visitor, visitor);
}
gc::Heap* heap = Runtime::Current()->GetHeap();
// Perform write barriers on copied object references.
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 4967a14a39..3cec29cd43 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -446,8 +446,9 @@ class MANAGED LOCKABLE Object {
}
// TODO fix thread safety analysis broken by the use of template. This should be
// SHARED_REQUIRES(Locks::mutator_lock_).
- template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
- typename Visitor, typename JavaLangRefVisitor = VoidFunctor>
+ template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+ typename Visitor,
+ typename JavaLangRefVisitor = VoidFunctor>
void VisitReferences(const Visitor& visitor, const JavaLangRefVisitor& ref_visitor)
NO_THREAD_SAFETY_ANALYSIS;
@@ -481,13 +482,13 @@ class MANAGED LOCKABLE Object {
}
// TODO: Fixme when anotatalysis works with visitors.
- template<bool kVisitClass, bool kIsStatic, typename Visitor>
+ template<bool kIsStatic, typename Visitor>
void VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) HOT_ATTR
NO_THREAD_SAFETY_ANALYSIS;
- template<bool kVisitClass, typename Visitor>
+ template<typename Visitor>
void VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) HOT_ATTR
SHARED_REQUIRES(Locks::mutator_lock_);
- template<bool kVisitClass, typename Visitor>
+ template<typename Visitor>
void VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) HOT_ATTR
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 4a7e7b35da..5b73557941 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -269,11 +269,8 @@ inline MemberOffset ObjectArray<T>::OffsetOfElement(int32_t i) {
(i * sizeof(HeapReference<Object>)));
}
-template<class T> template<const bool kVisitClass, typename Visitor>
+template<class T> template<typename Visitor>
void ObjectArray<T>::VisitReferences(const Visitor& visitor) {
- if (kVisitClass) {
- visitor(this, ClassOffset(), false);
- }
const size_t length = static_cast<size_t>(GetLength());
for (size_t i = 0; i < length; ++i) {
visitor(this, OffsetOfElement(i), false);
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 607b000488..b45cafd2a3 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -83,14 +83,15 @@ class MANAGED ObjectArray: public Array {
ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
+ static MemberOffset OffsetOfElement(int32_t i);
+
+ private:
// TODO fix thread safety analysis broken by the use of template. This should be
// SHARED_REQUIRES(Locks::mutator_lock_).
- template<const bool kVisitClass, typename Visitor>
+ template<typename Visitor>
void VisitReferences(const Visitor& visitor) NO_THREAD_SAFETY_ANALYSIS;
- static MemberOffset OffsetOfElement(int32_t i);
-
- private:
+ friend class Object; // For VisitReferences
DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectArray);
};