Add more read barriers to the class linker.
This change makes it possible to concurrently scan the remaining roots
in the class linker (the non-class-table roots that are visited by
ClassLinker::VisitRoots()) by adding read barriers.
Bug: 12687968
Change-Id: I66fecf7a303eee7537429e018f38da8270b18c67
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 16e0ec3..a40a2e4 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -41,7 +41,8 @@
inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class** element_class) {
for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
// Read the cached array class once to avoid races with other threads setting it.
- mirror::Class* array_class = find_array_class_cache_[i];
+ mirror::Class* array_class = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(
+ &find_array_class_cache_[i]);
if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
return array_class;
}
@@ -205,11 +206,20 @@
inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK(class_roots_ != NULL);
- mirror::Class* klass = class_roots_->Get(class_root);
+ mirror::ObjectArray<mirror::Class>* class_roots =
+ ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Class>, kWithReadBarrier>(
+ &class_roots_);
+ mirror::Class* klass = class_roots->Get(class_root);
DCHECK(klass != NULL);
return klass;
}
+inline mirror::DexCache* ClassLinker::GetDexCache(size_t idx) {
+ dex_lock_.AssertSharedHeld(Thread::Current());
+ DCHECK(idx < dex_caches_.size());
+ return ReadBarrier::BarrierForRoot<mirror::DexCache, kWithReadBarrier>(&dex_caches_[idx]);
+}
+
} // namespace art
#endif // ART_RUNTIME_CLASS_LINKER_INL_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d68aca9..61f94d4 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -408,8 +408,12 @@
CHECK(java_io_Serializable != NULL);
// We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to
// crawl up and explicitly list all of the supers as well.
- array_iftable_->SetInterface(0, java_lang_Cloneable);
- array_iftable_->SetInterface(1, java_io_Serializable);
+ {
+ mirror::IfTable* array_iftable =
+ ReadBarrier::BarrierForRoot<mirror::IfTable, kWithReadBarrier>(&array_iftable_);
+ array_iftable->SetInterface(0, java_lang_Cloneable);
+ array_iftable->SetInterface(1, java_io_Serializable);
+ }
// Sanity check Class[] and Object[]'s interfaces.
CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, class_array_class, 0));
@@ -2036,17 +2040,18 @@
RegisterDexFile(dex_file, dex_cache);
}
-bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) const {
+bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) {
dex_lock_.AssertSharedHeld(Thread::Current());
for (size_t i = 0; i != dex_caches_.size(); ++i) {
- if (dex_caches_[i]->GetDexFile() == &dex_file) {
+ mirror::DexCache* dex_cache = GetDexCache(i);
+ if (dex_cache->GetDexFile() == &dex_file) {
return true;
}
}
return false;
}
-bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) const {
+bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) {
ReaderMutexLock mu(Thread::Current(), dex_lock_);
return IsDexFileRegisteredLocked(dex_file);
}
@@ -2094,11 +2099,11 @@
RegisterDexFileLocked(dex_file, dex_cache);
}
-mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const {
+mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) {
ReaderMutexLock mu(Thread::Current(), dex_lock_);
// Search assuming unique-ness of dex file.
for (size_t i = 0; i != dex_caches_.size(); ++i) {
- mirror::DexCache* dex_cache = dex_caches_[i];
+ mirror::DexCache* dex_cache = GetDexCache(i);
if (dex_cache->GetDexFile() == &dex_file) {
return dex_cache;
}
@@ -2106,24 +2111,25 @@
// Search matching by location name.
std::string location(dex_file.GetLocation());
for (size_t i = 0; i != dex_caches_.size(); ++i) {
- mirror::DexCache* dex_cache = dex_caches_[i];
+ mirror::DexCache* dex_cache = GetDexCache(i);
if (dex_cache->GetDexFile()->GetLocation() == location) {
return dex_cache;
}
}
// Failure, dump diagnostic and abort.
for (size_t i = 0; i != dex_caches_.size(); ++i) {
- mirror::DexCache* dex_cache = dex_caches_[i];
+ mirror::DexCache* dex_cache = GetDexCache(i);
LOG(ERROR) << "Registered dex file " << i << " = " << dex_cache->GetDexFile()->GetLocation();
}
LOG(FATAL) << "Failed to find DexCache for DexFile " << location;
return NULL;
}
-void ClassLinker::FixupDexCaches(mirror::ArtMethod* resolution_method) const {
+void ClassLinker::FixupDexCaches(mirror::ArtMethod* resolution_method) {
ReaderMutexLock mu(Thread::Current(), dex_lock_);
for (size_t i = 0; i != dex_caches_.size(); ++i) {
- dex_caches_[i]->Fixup(resolution_method);
+ mirror::DexCache* dex_cache = GetDexCache(i);
+ dex_cache->Fixup(resolution_method);
}
}
@@ -2263,8 +2269,12 @@
// Use the single, global copies of "interfaces" and "iftable"
// (remember not to free them for arrays).
- CHECK(array_iftable_ != nullptr);
- new_class->SetIfTable(array_iftable_);
+ {
+ mirror::IfTable* array_iftable =
+ ReadBarrier::BarrierForRoot<mirror::IfTable, kWithReadBarrier>(&array_iftable_);
+ CHECK(array_iftable != nullptr);
+ new_class->SetIfTable(array_iftable);
+ }
// Inherit access flags from the component type.
int access_flags = new_class->GetComponentType()->GetAccessFlags();
@@ -2931,8 +2941,9 @@
mirror::ObjectArray<mirror::Class>* resolved_types = proxy_method->GetDexCacheResolvedTypes();
ReaderMutexLock mu(Thread::Current(), dex_lock_);
for (size_t i = 0; i != dex_caches_.size(); ++i) {
- if (dex_caches_[i]->GetResolvedTypes() == resolved_types) {
- dex_cache = dex_caches_[i];
+ mirror::DexCache* a_dex_cache = GetDexCache(i);
+ if (a_dex_cache->GetResolvedTypes() == resolved_types) {
+ dex_cache = a_dex_cache;
break;
}
}
@@ -4412,9 +4423,12 @@
DCHECK(klass != NULL);
DCHECK(klass->GetClassLoader() == NULL);
- DCHECK(class_roots_ != NULL);
- DCHECK(class_roots_->Get(class_root) == NULL);
- class_roots_->Set<false>(class_root, klass);
+ mirror::ObjectArray<mirror::Class>* class_roots =
+ ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Class>, kWithReadBarrier>(
+ &class_roots_);
+ DCHECK(class_roots != NULL);
+ DCHECK(class_roots->Get(class_root) == NULL);
+ class_roots->Set<false>(class_root, klass);
}
} // namespace art
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 62b5ea8..7d7bf15 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -28,6 +28,7 @@
#include "jni.h"
#include "oat_file.h"
#include "object_callbacks.h"
+#include "read_barrier.h"
namespace art {
namespace gc {
@@ -252,12 +253,12 @@
void VisitRoots(RootCallback* callback, void* arg, VisitRootFlags flags)
LOCKS_EXCLUDED(dex_lock_);
- mirror::DexCache* FindDexCache(const DexFile& dex_file) const
+ mirror::DexCache* FindDexCache(const DexFile& dex_file)
LOCKS_EXCLUDED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsDexFileRegistered(const DexFile& dex_file) const
+ bool IsDexFileRegistered(const DexFile& dex_file)
LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FixupDexCaches(mirror::ArtMethod* resolution_method) const
+ void FixupDexCaches(mirror::ArtMethod* resolution_method)
LOCKS_EXCLUDED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -470,7 +471,7 @@
void RegisterDexFileLocked(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache)
EXCLUSIVE_LOCKS_REQUIRED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsDexFileRegisteredLocked(const DexFile& dex_file) const
+ bool IsDexFileRegisteredLocked(const DexFile& dex_file)
SHARED_LOCKS_REQUIRED(dex_lock_, Locks::mutator_lock_);
bool InitializeClass(Handle<mirror::Class> klass, bool can_run_clinit,
@@ -532,9 +533,14 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// For use by ImageWriter to find DexCaches for its roots
- const std::vector<mirror::DexCache*>& GetDexCaches() {
- return dex_caches_;
+ ReaderWriterMutex* DexLock()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCK_RETURNED(dex_lock_) {
+ return &dex_lock_;
}
+ size_t GetDexCacheCount() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, dex_lock_) {
+ return dex_caches_.size();
+ }
+ mirror::DexCache* GetDexCache(size_t idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, dex_lock_);
const OatFile* FindOpenedOatFileForDexFile(const DexFile& dex_file)
LOCKS_EXCLUDED(dex_lock_)
@@ -643,9 +649,12 @@
void SetClassRoot(ClassRoot class_root, mirror::Class* klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ObjectArray<mirror::Class>* GetClassRoots() {
- DCHECK(class_roots_ != NULL);
- return class_roots_;
+ mirror::ObjectArray<mirror::Class>* GetClassRoots() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ mirror::ObjectArray<mirror::Class>* class_roots =
+ ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Class>, kWithReadBarrier>(
+ &class_roots_);
+ DCHECK(class_roots != NULL);
+ return class_roots;
}
static const char* class_roots_descriptors_[];