diff options
| -rw-r--r-- | compiler/image_writer.cc | 35 | ||||
| -rw-r--r-- | runtime/class_linker-inl.h | 14 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 50 | ||||
| -rw-r--r-- | runtime/class_linker.h | 27 |
4 files changed, 90 insertions, 36 deletions
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index ca1239f18d..6e5f19a8c5 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -263,7 +263,11 @@ void ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg) { } mirror::String* string = obj->AsString(); const uint16_t* utf16_string = string->GetCharArray()->GetData() + string->GetOffset(); - for (DexCache* dex_cache : Runtime::Current()->GetClassLinker()->GetDexCaches()) { + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock()); + size_t dex_cache_count = class_linker->GetDexCacheCount(); + for (size_t i = 0; i < dex_cache_count; ++i) { + DexCache* dex_cache = class_linker->GetDexCache(i); const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::StringId* string_id; if (UNLIKELY(string->GetLength() == 0)) { @@ -316,7 +320,10 @@ void ImageWriter::PruneNonImageClasses() { // Clear references to removed classes from the DexCaches. ArtMethod* resolution_method = runtime->GetResolutionMethod(); - for (DexCache* dex_cache : class_linker->GetDexCaches()) { + ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock()); + size_t dex_cache_count = class_linker->GetDexCacheCount(); + for (size_t idx = 0; idx < dex_cache_count; ++idx) { + DexCache* dex_cache = class_linker->GetDexCache(idx); for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { Class* klass = dex_cache->GetResolvedType(i); if (klass != NULL && !IsImageClass(klass)) { @@ -408,13 +415,27 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { Handle<Class> object_array_class(hs.NewHandle( class_linker->FindSystemClass(self, "[Ljava/lang/Object;"))); - // build an Object[] of all the DexCaches used in the source_space_ + // build an Object[] of all the DexCaches used in the source_space_. + // Since we can't hold the dex lock when allocating the dex_caches + // ObjectArray, we lock the dex lock twice, first to get the number + // of dex caches first and then lock it again to copy the dex + // caches. We check that the number of dex caches does not change. + size_t dex_cache_count; + { + ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock()); + dex_cache_count = class_linker->GetDexCacheCount(); + } Handle<ObjectArray<Object>> dex_caches( hs.NewHandle(ObjectArray<Object>::Alloc(self, object_array_class.Get(), - class_linker->GetDexCaches().size()))); - int i = 0; - for (DexCache* dex_cache : class_linker->GetDexCaches()) { - dex_caches->Set<false>(i++, dex_cache); + dex_cache_count))); + CHECK(dex_caches.Get() != nullptr) << "Failed to allocate a dex cache array."; + { + ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock()); + CHECK_EQ(dex_cache_count, class_linker->GetDexCacheCount()) + << "The number of dex caches changed."; + for (size_t i = 0; i < dex_cache_count; ++i) { + dex_caches->Set<false>(i, class_linker->GetDexCache(i)); + } } // build an Object[] of the roots needed to restore the runtime diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 16e0ec3080..a40a2e4cd2 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -41,7 +41,8 @@ inline mirror::Class* ClassLinker::FindSystemClass(Thread* self, const char* des 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::ObjectArray<mirror::ArtField>* ClassLinker::AllocArtFieldArray(Th 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 d68aca9865..61f94d4cbf 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -408,8 +408,12 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class 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 @@ void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, 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 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file, 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 @@ mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const { // 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 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto // 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::ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, 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 @@ void ClassLinker::SetClassRoot(ClassRoot class_root, mirror::Class* klass) { 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 62b5ea8b6d..7d7bf15ee0 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 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { 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_[]; |