diff options
Diffstat (limited to 'runtime')
41 files changed, 397 insertions, 324 deletions
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 25eb3a342d..cf25810a21 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_CLASS_LINKER_INL_H_ #include "class_linker.h" +#include "gc_root-inl.h" #include "gc/heap-inl.h" #include "mirror/art_field.h" #include "mirror/class_loader.h" @@ -40,8 +41,7 @@ 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 = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>( - &find_array_class_cache_[i]); + mirror::Class* array_class = find_array_class_cache_[i].Read(); if (array_class != nullptr && array_class->GetComponentType() == *element_class) { return array_class; } @@ -54,7 +54,7 @@ inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class** mirror::Class* array_class = FindClass(self, descriptor.c_str(), class_loader); // Benign races in storing array class and incrementing index. size_t victim_index = find_array_class_cache_next_victim_; - find_array_class_cache_[victim_index] = array_class; + find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class); find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize; return array_class; } @@ -204,10 +204,8 @@ 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::ObjectArray<mirror::Class>* class_roots = - ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Class>, kWithReadBarrier>( - &class_roots_); + DCHECK(!class_roots_.IsNull()); + mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); mirror::Class* klass = class_roots->Get(class_root); DCHECK(klass != NULL); return klass; @@ -216,7 +214,7 @@ inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) 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]); + return dex_caches_[idx].Read(); } } // namespace art diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 5599c212c1..12b7680d8e 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -34,6 +34,7 @@ #include "compiler_callbacks.h" #include "debugger.h" #include "dex_file-inl.h" +#include "gc_root-inl.h" #include "gc/accounting/card_table-inl.h" #include "gc/accounting/heap_bitmap.h" #include "gc/heap.h" @@ -267,9 +268,10 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class java_lang_ref_Reference->SetStatus(mirror::Class::kStatusResolved, self); // Create storage for root classes, save away our work so far (requires descriptors). - class_roots_ = mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(), - kClassRootsMax); - CHECK(class_roots_ != NULL); + class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class> >( + mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(), + kClassRootsMax)); + CHECK(!class_roots_.IsNull()); SetClassRoot(kJavaLangClass, java_lang_Class.Get()); SetClassRoot(kJavaLangObject, java_lang_Object.Get()); SetClassRoot(kClassArrayClass, class_array_class.Get()); @@ -289,7 +291,7 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid)); // Create array interface entries to populate once we can load system classes. - array_iftable_ = AllocIfTable(self, 2); + array_iftable_ = GcRoot<mirror::IfTable>(AllocIfTable(self, 2)); // Create int array type for AllocDexCache (done in AppendToBootClassPath). Handle<mirror::Class> int_array_class(hs.NewHandle( @@ -428,8 +430,7 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class // 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. { - mirror::IfTable* array_iftable = - ReadBarrier::BarrierForRoot<mirror::IfTable, kWithReadBarrier>(&array_iftable_); + mirror::IfTable* array_iftable = array_iftable_.Read(); array_iftable->SetInterface(0, java_lang_Cloneable); array_iftable->SetInterface(1, java_io_Serializable); } @@ -559,7 +560,7 @@ void ClassLinker::FinishInit(Thread* self) { // if possible add new checks there to catch errors early } - CHECK(array_iftable_ != NULL); + CHECK(!array_iftable_.IsNull()); // disable the slow paths in FindClass and CreatePrimitiveClass now // that Object, Class, and Object[] are setup @@ -1466,7 +1467,7 @@ void ClassLinker::InitFromImage() { Handle<mirror::ObjectArray<mirror::Class>> class_roots(hs.NewHandle( space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)-> AsObjectArray<mirror::Class>())); - class_roots_ = class_roots.Get(); + class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(class_roots.Get()); // Special case of setting up the String class early so that we can test arbitrary objects // as being Strings or not @@ -1506,11 +1507,11 @@ void ClassLinker::InitFromImage() { // reinit class_roots_ mirror::Class::SetClassClass(class_roots->Get(kJavaLangClass)); - class_roots_ = class_roots.Get(); + class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(class_roots.Get()); // reinit array_iftable_ from any array class instance, they should be == - array_iftable_ = GetClassRoot(kObjectArrayClass)->GetIfTable(); - DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable()); + array_iftable_ = GcRoot<mirror::IfTable>(GetClassRoot(kObjectArrayClass)->GetIfTable()); + DCHECK(array_iftable_.Read() == GetClassRoot(kBooleanArrayClass)->GetIfTable()); // String class root was set above mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference)); mirror::ArtField::SetClass(GetClassRoot(kJavaLangReflectArtField)); @@ -1533,22 +1534,23 @@ void ClassLinker::InitFromImage() { void ClassLinker::VisitClassRoots(RootCallback* callback, void* arg, VisitRootFlags flags) { WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); if ((flags & kVisitRootFlagAllRoots) != 0) { - for (std::pair<const size_t, mirror::Class*>& it : class_table_) { - callback(reinterpret_cast<mirror::Object**>(&it.second), arg, 0, kRootStickyClass); + for (std::pair<const size_t, GcRoot<mirror::Class> >& it : class_table_) { + it.second.VisitRoot(callback, arg, 0, kRootStickyClass); } } else if ((flags & kVisitRootFlagNewRoots) != 0) { for (auto& pair : new_class_roots_) { - mirror::Object* old_ref = pair.second; - callback(reinterpret_cast<mirror::Object**>(&pair.second), arg, 0, kRootStickyClass); - if (UNLIKELY(pair.second != old_ref)) { + mirror::Class* old_ref = pair.second.Read<kWithoutReadBarrier>(); + pair.second.VisitRoot(callback, arg, 0, kRootStickyClass); + mirror::Class* new_ref = pair.second.Read<kWithoutReadBarrier>(); + if (UNLIKELY(new_ref != old_ref)) { // Uh ohes, GC moved a root in the log. Need to search the class_table and update the // corresponding object. This is slow, but luckily for us, this may only happen with a // concurrent moving GC. for (auto it = class_table_.lower_bound(pair.first), end = class_table_.end(); it != end && it->first == pair.first; ++it) { // If the class stored matches the old class, update it to the new value. - if (old_ref == it->second) { - it->second = pair.second; + if (old_ref == it->second.Read<kWithoutReadBarrier>()) { + it->second = GcRoot<mirror::Class>(new_ref); } } } @@ -1570,17 +1572,17 @@ void ClassLinker::VisitClassRoots(RootCallback* callback, void* arg, VisitRootFl // reinit references to when reinitializing a ClassLinker from a // mapped image. void ClassLinker::VisitRoots(RootCallback* callback, void* arg, VisitRootFlags flags) { - callback(reinterpret_cast<mirror::Object**>(&class_roots_), arg, 0, kRootVMInternal); + class_roots_.VisitRoot(callback, arg, 0, kRootVMInternal); Thread* self = Thread::Current(); { ReaderMutexLock mu(self, dex_lock_); if ((flags & kVisitRootFlagAllRoots) != 0) { - for (mirror::DexCache*& dex_cache : dex_caches_) { - callback(reinterpret_cast<mirror::Object**>(&dex_cache), arg, 0, kRootVMInternal); + for (GcRoot<mirror::DexCache>& dex_cache : dex_caches_) { + dex_cache.VisitRoot(callback, arg, 0, kRootVMInternal); } } else if ((flags & kVisitRootFlagNewRoots) != 0) { for (size_t index : new_dex_cache_roots_) { - callback(reinterpret_cast<mirror::Object**>(&dex_caches_[index]), arg, 0, kRootVMInternal); + dex_caches_[index].VisitRoot(callback, arg, 0, kRootVMInternal); } } if ((flags & kVisitRootFlagClearRootLog) != 0) { @@ -1593,12 +1595,11 @@ void ClassLinker::VisitRoots(RootCallback* callback, void* arg, VisitRootFlags f } } VisitClassRoots(callback, arg, flags); - callback(reinterpret_cast<mirror::Object**>(&array_iftable_), arg, 0, kRootVMInternal); - DCHECK(array_iftable_ != nullptr); + array_iftable_.VisitRoot(callback, arg, 0, kRootVMInternal); + DCHECK(!array_iftable_.IsNull()); for (size_t i = 0; i < kFindArrayCacheSize; ++i) { - if (find_array_class_cache_[i] != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&find_array_class_cache_[i]), arg, 0, - kRootVMInternal); + if (!find_array_class_cache_[i].IsNull()) { + find_array_class_cache_[i].VisitRoot(callback, arg, 0, kRootVMInternal); } } } @@ -1608,9 +1609,8 @@ void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) { MoveImageClassesToClassTable(); } WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); - for (std::pair<const size_t, mirror::Class*>& it : class_table_) { - mirror::Class** root = &it.second; - mirror::Class* c = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(root); + for (std::pair<const size_t, GcRoot<mirror::Class> >& it : class_table_) { + mirror::Class* c = it.second.Read(); if (!visitor(c, arg)) { return; } @@ -2536,7 +2536,7 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, CHECK(dex_cache.Get() != NULL) << dex_file.GetLocation(); CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation())) << dex_cache->GetLocation()->ToModifiedUtf8() << " " << dex_file.GetLocation(); - dex_caches_.push_back(dex_cache.Get()); + dex_caches_.push_back(GcRoot<mirror::DexCache>(dex_cache.Get())); dex_cache->SetDexFile(&dex_file); if (log_new_dex_caches_roots_) { // TODO: This is not safe if we can remove dex caches. @@ -2753,8 +2753,7 @@ 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). { - mirror::IfTable* array_iftable = - ReadBarrier::BarrierForRoot<mirror::IfTable, kWithReadBarrier>(&array_iftable_); + mirror::IfTable* array_iftable = array_iftable_.Read(); CHECK(array_iftable != nullptr); new_class->SetIfTable(array_iftable); } @@ -2838,9 +2837,9 @@ mirror::Class* ClassLinker::InsertClass(const char* descriptor, mirror::Class* k } } VerifyObject(klass); - class_table_.insert(std::make_pair(hash, klass)); + class_table_.insert(std::make_pair(hash, GcRoot<mirror::Class>(klass))); if (log_new_class_table_roots_) { - new_class_roots_.push_back(std::make_pair(hash, klass)); + new_class_roots_.push_back(std::make_pair(hash, GcRoot<mirror::Class>(klass))); } return NULL; } @@ -2862,8 +2861,7 @@ mirror::Class* ClassLinker::UpdateClass(const char* descriptor, mirror::Class* k for (auto it = class_table_.lower_bound(hash), end = class_table_.end(); it != end && it->first == hash; ++it) { - mirror::Class** root = &it->second; - mirror::Class* klass = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(root); + mirror::Class* klass = it->second.Read(); if (klass == existing) { class_table_.erase(it); break; @@ -2882,9 +2880,9 @@ mirror::Class* ClassLinker::UpdateClass(const char* descriptor, mirror::Class* k } VerifyObject(klass); - class_table_.insert(std::make_pair(hash, klass)); + class_table_.insert(std::make_pair(hash, GcRoot<mirror::Class>(klass))); if (log_new_class_table_roots_) { - new_class_roots_.push_back(std::make_pair(hash, klass)); + new_class_roots_.push_back(std::make_pair(hash, GcRoot<mirror::Class>(klass))); } return existing; @@ -2896,8 +2894,7 @@ bool ClassLinker::RemoveClass(const char* descriptor, const mirror::ClassLoader* for (auto it = class_table_.lower_bound(hash), end = class_table_.end(); it != end && it->first == hash; ++it) { - mirror::Class** root = &it->second; - mirror::Class* klass = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(root); + mirror::Class* klass = it->second.Read(); if (klass->GetClassLoader() == class_loader && klass->DescriptorEquals(descriptor)) { class_table_.erase(it); return true; @@ -2941,14 +2938,12 @@ mirror::Class* ClassLinker::LookupClassFromTableLocked(const char* descriptor, size_t hash) { auto end = class_table_.end(); for (auto it = class_table_.lower_bound(hash); it != end && it->first == hash; ++it) { - mirror::Class** root = &it->second; - mirror::Class* klass = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(root); + mirror::Class* klass = it->second.Read(); if (klass->GetClassLoader() == class_loader && klass->DescriptorEquals(descriptor)) { if (kIsDebugBuild) { // Check for duplicates in the table. for (++it; it != end && it->first == hash; ++it) { - mirror::Class** root2 = &it->second; - mirror::Class* klass2 = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(root2); + mirror::Class* klass2 = it->second.Read(); CHECK(!(klass2->GetClassLoader() == class_loader && klass2->DescriptorEquals(descriptor))) << PrettyClass(klass) << " " << klass << " " << klass->GetClassLoader() << " " @@ -2992,9 +2987,9 @@ void ClassLinker::MoveImageClassesToClassTable() { CHECK(existing == klass) << PrettyClassAndClassLoader(existing) << " != " << PrettyClassAndClassLoader(klass); } else { - class_table_.insert(std::make_pair(hash, klass)); + class_table_.insert(std::make_pair(hash, GcRoot<mirror::Class>(klass))); if (log_new_class_table_roots_) { - new_class_roots_.push_back(std::make_pair(hash, klass)); + new_class_roots_.push_back(std::make_pair(hash, GcRoot<mirror::Class>(klass))); } } } @@ -3040,8 +3035,7 @@ void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Clas ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); for (auto it = class_table_.lower_bound(hash), end = class_table_.end(); it != end && it->first == hash; ++it) { - mirror::Class** root = &it->second; - mirror::Class* klass = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(root); + mirror::Class* klass = it->second.Read(); if (klass->DescriptorEquals(descriptor)) { result.push_back(klass); } @@ -5017,9 +5011,8 @@ void ClassLinker::DumpAllClasses(int flags) { std::vector<mirror::Class*> all_classes; { ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); - for (std::pair<const size_t, mirror::Class*>& it : class_table_) { - mirror::Class** root = &it.second; - mirror::Class* klass = ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(root); + for (std::pair<const size_t, GcRoot<mirror::Class> >& it : class_table_) { + mirror::Class* klass = it.second.Read(); all_classes.push_back(klass); } } @@ -5059,9 +5052,7 @@ void ClassLinker::SetClassRoot(ClassRoot class_root, mirror::Class* klass) { DCHECK(klass != NULL); DCHECK(klass->GetClassLoader() == NULL); - mirror::ObjectArray<mirror::Class>* class_roots = - ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::Class>, kWithReadBarrier>( - &class_roots_); + mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); DCHECK(class_roots != NULL); DCHECK(class_roots->Get(class_root) == NULL); class_roots->Set<false>(class_root, klass); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index b108f61e8b..1bb1635b28 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -24,11 +24,11 @@ #include "base/macros.h" #include "base/mutex.h" #include "dex_file.h" +#include "gc_root.h" #include "gtest/gtest.h" #include "jni.h" #include "oat_file.h" #include "object_callbacks.h" -#include "read_barrier.h" namespace art { @@ -245,9 +245,11 @@ class ClassLinker { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void VisitClassRoots(RootCallback* callback, void* arg, VisitRootFlags flags) - LOCKS_EXCLUDED(Locks::classlinker_classes_lock_); + LOCKS_EXCLUDED(Locks::classlinker_classes_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void VisitRoots(RootCallback* callback, void* arg, VisitRootFlags flags) - LOCKS_EXCLUDED(dex_lock_); + LOCKS_EXCLUDED(dex_lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::DexCache* FindDexCache(const DexFile& dex_file) LOCKS_EXCLUDED(dex_lock_) @@ -378,9 +380,7 @@ class ClassLinker { mirror::ArtMethod* AllocArtMethod(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 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_); + mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); DCHECK(class_roots != NULL); return class_roots; } @@ -609,18 +609,18 @@ class ClassLinker { mutable ReaderWriterMutex dex_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; std::vector<size_t> new_dex_cache_roots_ GUARDED_BY(dex_lock_);; - std::vector<mirror::DexCache*> dex_caches_ GUARDED_BY(dex_lock_); + std::vector<GcRoot<mirror::DexCache>> dex_caches_ GUARDED_BY(dex_lock_); std::vector<const OatFile*> oat_files_ GUARDED_BY(dex_lock_); // multimap from a string hash code of a class descriptor to // mirror::Class* instances. Results should be compared for a matching // Class::descriptor_ and Class::class_loader_. - typedef std::multimap<size_t, mirror::Class*> Table; + typedef std::multimap<size_t, GcRoot<mirror::Class>> Table; // This contains strong roots. To enable concurrent root scanning of // the class table, be careful to use a read barrier when accessing this. Table class_table_ GUARDED_BY(Locks::classlinker_classes_lock_); - std::vector<std::pair<size_t, mirror::Class*>> new_class_roots_; + std::vector<std::pair<size_t, GcRoot<mirror::Class>>> new_class_roots_; // Do we need to search dex caches to find image classes? bool dex_cache_image_class_lookup_required_; @@ -694,7 +694,7 @@ class ClassLinker { kJavaLangStackTraceElementArrayClass, kClassRootsMax, }; - mirror::ObjectArray<mirror::Class>* class_roots_; + GcRoot<mirror::ObjectArray<mirror::Class>> class_roots_; mirror::Class* GetClassRoot(ClassRoot class_root) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -710,12 +710,12 @@ class ClassLinker { } // The interface table used by all arrays. - mirror::IfTable* array_iftable_; + GcRoot<mirror::IfTable> array_iftable_; // A cache of the last FindArrayClass results. The cache serves to avoid creating array class // descriptors for the sake of performing FindClass. static constexpr size_t kFindArrayCacheSize = 16; - mirror::Class* find_array_class_cache_[kFindArrayCacheSize]; + GcRoot<mirror::Class> find_array_class_cache_[kFindArrayCacheSize]; size_t find_array_class_cache_next_victim_; bool init_done_; diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index a43a645c8d..8e363c4fa3 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -30,6 +30,7 @@ #include "class_linker.h" #include "compiler_callbacks.h" #include "dex_file.h" +#include "gc_root-inl.h" #include "gc/heap.h" #include "gtest/gtest.h" #include "jni_internal.h" diff --git a/runtime/gc_root-inl.h b/runtime/gc_root-inl.h new file mode 100644 index 0000000000..482f7bca0e --- /dev/null +++ b/runtime/gc_root-inl.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_GC_ROOT_INL_H_ +#define ART_RUNTIME_GC_ROOT_INL_H_ + +#include "gc_root.h" + +#include "read_barrier-inl.h" + +namespace art { + +template<class MirrorType> +template<ReadBarrierOption kReadBarrierOption> +inline MirrorType* GcRoot<MirrorType>::Read() { + return ReadBarrier::BarrierForRoot<MirrorType, kReadBarrierOption>(&root_); +} + +} // namespace art +#endif // ART_RUNTIME_GC_ROOT_INL_H_ diff --git a/runtime/gc_root.h b/runtime/gc_root.h new file mode 100644 index 0000000000..86a8847431 --- /dev/null +++ b/runtime/gc_root.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_GC_ROOT_H_ +#define ART_RUNTIME_GC_ROOT_H_ + +#include "base/mutex.h" // For Locks::mutator_lock_. +#include "object_callbacks.h" + +namespace art { + +template<class MirrorType> +class GcRoot { + public: + template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> + ALWAYS_INLINE MirrorType* Read() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void VisitRoot(RootCallback* callback, void* arg, uint32_t thread_id, RootType root_type) { + callback(reinterpret_cast<mirror::Object**>(&root_), arg, thread_id, root_type); + } + + // This is only used by IrtIterator. + ALWAYS_INLINE MirrorType** AddressWithoutBarrier() { + return &root_; + } + + bool IsNull() const { + // It's safe to null-check it without a read barrier. + return root_ == nullptr; + } + + ALWAYS_INLINE explicit GcRoot<MirrorType>() : root_(nullptr) { + } + + ALWAYS_INLINE explicit GcRoot<MirrorType>(MirrorType* ref) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : root_(ref) { + } + + private: + MirrorType* root_; +}; + +} // namespace art + +#endif // ART_RUNTIME_GC_ROOT_H_ diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h index f561643399..c826716787 100644 --- a/runtime/indirect_reference_table-inl.h +++ b/runtime/indirect_reference_table-inl.h @@ -46,7 +46,7 @@ inline bool IndirectReferenceTable::GetChecked(IndirectRef iref) const { AbortIfNoCheckJNI(); return false; } - if (UNLIKELY(table_[idx] == nullptr)) { + if (UNLIKELY(table_[idx].IsNull())) { LOG(ERROR) << "JNI ERROR (app bug): accessed deleted " << kind_ << " " << iref; AbortIfNoCheckJNI(); return false; @@ -75,11 +75,11 @@ inline mirror::Object* IndirectReferenceTable::Get(IndirectRef iref) const { if (!GetChecked(iref)) { return kInvalidIndirectRefObject; } - mirror::Object** root = &table_[ExtractIndex(iref)]; - mirror::Object* obj = *root; + uint32_t idx = ExtractIndex(iref); + mirror::Object* obj = table_[idx].Read<kWithoutReadBarrier>(); if (LIKELY(obj != kClearedJniWeakGlobal)) { // The read barrier or VerifyObject won't handle kClearedJniWeakGlobal. - obj = ReadBarrier::BarrierForRoot<mirror::Object, kReadBarrierOption>(root); + obj = table_[idx].Read(); VerifyObject(obj); } return obj; diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index 26ddba23f2..9b2b82e477 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -76,7 +76,7 @@ IndirectReferenceTable::IndirectReferenceTable(size_t initialCount, CHECK(table_mem_map_.get() != nullptr) << error_str; CHECK_EQ(table_mem_map_->Size(), table_bytes); - table_ = reinterpret_cast<mirror::Object**>(table_mem_map_->Begin()); + table_ = reinterpret_cast<GcRoot<mirror::Object>*>(table_mem_map_->Begin()); CHECK(table_ != nullptr); memset(table_, 0xd1, initial_bytes); @@ -132,20 +132,22 @@ IndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) { if (numHoles > 0) { DCHECK_GT(topIndex, 1U); // Find the first hole; likely to be near the end of the list. - mirror::Object** pScan = &table_[topIndex - 1]; - DCHECK(*pScan != NULL); - while (*--pScan != NULL) { + GcRoot<mirror::Object>* pScan = &table_[topIndex - 1]; + DCHECK(!pScan->IsNull()); + --pScan; + while (!pScan->IsNull()) { DCHECK_GE(pScan, table_ + prevState.parts.topIndex); + --pScan; } UpdateSlotAdd(obj, pScan - table_); result = ToIndirectRef(pScan - table_); - *pScan = obj; + *pScan = GcRoot<mirror::Object>(obj); segment_state_.parts.numHoles--; } else { // Add to the end. UpdateSlotAdd(obj, topIndex); result = ToIndirectRef(topIndex); - table_[topIndex++] = obj; + table_[topIndex++] = GcRoot<mirror::Object>(obj); segment_state_.parts.topIndex = topIndex; } if (false) { @@ -211,15 +213,16 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { return false; } - table_[idx] = NULL; + table_[idx] = GcRoot<mirror::Object>(nullptr); int numHoles = segment_state_.parts.numHoles - prevState.parts.numHoles; if (numHoles != 0) { while (--topIndex > bottomIndex && numHoles != 0) { if (false) { LOG(INFO) << "+++ checking for hole at " << topIndex-1 - << " (cookie=" << cookie << ") val=" << table_[topIndex - 1]; + << " (cookie=" << cookie << ") val=" + << table_[topIndex - 1].Read<kWithoutReadBarrier>(); } - if (table_[topIndex-1] != NULL) { + if (!table_[topIndex-1].IsNull()) { break; } if (false) { @@ -239,7 +242,7 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { // Not the top-most entry. This creates a hole. We NULL out the // entry to prevent somebody from deleting it twice and screwing up // the hole count. - if (table_[idx] == NULL) { + if (table_[idx].IsNull()) { LOG(INFO) << "--- WEIRD: removing null entry " << idx; return false; } @@ -247,7 +250,7 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { return false; } - table_[idx] = NULL; + table_[idx] = GcRoot<mirror::Object>(nullptr); segment_state_.parts.numHoles++; if (false) { LOG(INFO) << "+++ left hole at " << idx << ", holes=" << segment_state_.parts.numHoles; @@ -269,17 +272,16 @@ void IndirectReferenceTable::Dump(std::ostream& os) const { os << kind_ << " table dump:\n"; ReferenceTable::Table entries; for (size_t i = 0; i < Capacity(); ++i) { - mirror::Object** root = &table_[i]; - mirror::Object* obj = *root; + mirror::Object* obj = table_[i].Read<kWithoutReadBarrier>(); if (UNLIKELY(obj == nullptr)) { // Remove NULLs. } else if (UNLIKELY(obj == kClearedJniWeakGlobal)) { // ReferenceTable::Dump() will handle kClearedJniWeakGlobal // while the read barrier won't. - entries.push_back(obj); + entries.push_back(GcRoot<mirror::Object>(obj)); } else { - obj = ReadBarrier::BarrierForRoot<mirror::Object, kWithReadBarrier>(root); - entries.push_back(obj); + obj = table_[i].Read(); + entries.push_back(GcRoot<mirror::Object>(obj)); } } ReferenceTable::Dump(os, entries); diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index b3a855dfb3..fb910e2943 100644 --- a/runtime/indirect_reference_table.h +++ b/runtime/indirect_reference_table.h @@ -24,10 +24,11 @@ #include "base/logging.h" #include "base/mutex.h" +#include "gc_root.h" #include "mem_map.h" #include "object_callbacks.h" #include "offsets.h" -#include "read_barrier.h" +#include "read_barrier_option.h" namespace art { namespace mirror { @@ -204,12 +205,13 @@ union IRTSegmentState { class IrtIterator { public: - explicit IrtIterator(mirror::Object** table, size_t i, size_t capacity) + explicit IrtIterator(GcRoot<mirror::Object>* table, size_t i, size_t capacity) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : table_(table), i_(i), capacity_(capacity) { SkipNullsAndTombstones(); } - IrtIterator& operator++() { + IrtIterator& operator++() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ++i_; SkipNullsAndTombstones(); return *this; @@ -217,7 +219,7 @@ class IrtIterator { mirror::Object** operator*() { // This does not have a read barrier as this is used to visit roots. - return &table_[i_]; + return table_[i_].AddressWithoutBarrier(); } bool equals(const IrtIterator& rhs) const { @@ -225,14 +227,16 @@ class IrtIterator { } private: - void SkipNullsAndTombstones() { + void SkipNullsAndTombstones() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // We skip NULLs and tombstones. Clients don't want to see implementation details. - while (i_ < capacity_ && (table_[i_] == NULL || table_[i_] == kClearedJniWeakGlobal)) { + while (i_ < capacity_ && + (table_[i_].IsNull() || + table_[i_].Read<kWithoutReadBarrier>() == kClearedJniWeakGlobal)) { ++i_; } } - mirror::Object** const table_; + GcRoot<mirror::Object>* const table_; size_t i_; size_t capacity_; }; @@ -309,7 +313,8 @@ class IndirectReferenceTable { return IrtIterator(table_, Capacity(), Capacity()); } - void VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type); + void VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); uint32_t GetSegmentState() const { return segment_state_.all; @@ -373,7 +378,7 @@ class IndirectReferenceTable { std::unique_ptr<MemMap> slot_mem_map_; // bottom of the stack. Do not directly access the object references // in this as they are roots. Use Get() that has a read barrier. - mirror::Object** table_; + GcRoot<mirror::Object>* table_; /* bit mask, ORed into all irefs */ IndirectRefKind kind_; /* extended debugging info */ diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 8e375cf4d0..16be077de1 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -25,6 +25,7 @@ #include "debugger.h" #include "dex_file-inl.h" #include "entrypoints/quick/quick_alloc_entrypoints.h" +#include "gc_root-inl.h" #include "interpreter/interpreter.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" @@ -628,7 +629,7 @@ bool Instrumentation::AddDeoptimizedMethod(mirror::ArtMethod* method) { } // Not found. Add it. int32_t hash_code = method->IdentityHashCode(); - deoptimized_methods_.insert(std::make_pair(hash_code, method)); + deoptimized_methods_.insert(std::make_pair(hash_code, GcRoot<mirror::ArtMethod>(method))); return true; } @@ -636,8 +637,7 @@ bool Instrumentation::FindDeoptimizedMethod(mirror::ArtMethod* method) { int32_t hash_code = method->IdentityHashCode(); auto range = deoptimized_methods_.equal_range(hash_code); for (auto it = range.first; it != range.second; ++it) { - mirror::ArtMethod** root = &it->second; - mirror::ArtMethod* m = ReadBarrier::BarrierForRoot<mirror::ArtMethod>(root); + mirror::ArtMethod* m = it->second.Read(); if (m == method) { // Found. return true; @@ -653,16 +653,14 @@ mirror::ArtMethod* Instrumentation::BeginDeoptimizedMethod() { // Empty. return nullptr; } - mirror::ArtMethod** root = &it->second; - return ReadBarrier::BarrierForRoot<mirror::ArtMethod>(root); + return it->second.Read(); } bool Instrumentation::RemoveDeoptimizedMethod(mirror::ArtMethod* method) { int32_t hash_code = method->IdentityHashCode(); auto range = deoptimized_methods_.equal_range(hash_code); for (auto it = range.first; it != range.second; ++it) { - mirror::ArtMethod** root = &it->second; - mirror::ArtMethod* m = ReadBarrier::BarrierForRoot<mirror::ArtMethod>(root); + mirror::ArtMethod* m = it->second.Read(); if (m == method) { // Found. Erase and return. deoptimized_methods_.erase(it); @@ -1024,8 +1022,7 @@ void Instrumentation::VisitRoots(RootCallback* callback, void* arg) { return; } for (auto pair : deoptimized_methods_) { - mirror::ArtMethod** root = &pair.second; - callback(reinterpret_cast<mirror::Object**>(root), arg, 0, kRootVMInternal); + pair.second.VisitRoot(callback, arg, 0, kRootVMInternal); } } diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h index cabb0e9c27..66c6b388d4 100644 --- a/runtime/instrumentation.h +++ b/runtime/instrumentation.h @@ -25,6 +25,7 @@ #include "instruction_set.h" #include "base/macros.h" #include "base/mutex.h" +#include "gc_root.h" #include "object_callbacks.h" namespace art { @@ -440,7 +441,8 @@ class Instrumentation { // The set of methods being deoptimized (by the debugger) which must be executed with interpreter // only. mutable ReaderWriterMutex deoptimized_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - std::multimap<int32_t, mirror::ArtMethod*> deoptimized_methods_ GUARDED_BY(deoptimized_methods_lock_); + std::multimap<int32_t, GcRoot<mirror::ArtMethod>> deoptimized_methods_ + GUARDED_BY(deoptimized_methods_lock_); bool deoptimization_enabled_; // Current interpreter handler table. This is updated each time the thread state flags are diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc index 14305006e4..aadd85a0f4 100644 --- a/runtime/intern_table.cc +++ b/runtime/intern_table.cc @@ -58,27 +58,27 @@ void InternTable::VisitRoots(RootCallback* callback, void* arg, VisitRootFlags f MutexLock mu(Thread::Current(), *Locks::intern_table_lock_); if ((flags & kVisitRootFlagAllRoots) != 0) { for (auto& strong_intern : strong_interns_) { - callback(reinterpret_cast<mirror::Object**>(&strong_intern.second), arg, 0, - kRootInternedString); - DCHECK(strong_intern.second != nullptr); + strong_intern.second.VisitRoot(callback, arg, 0, kRootInternedString); + DCHECK(!strong_intern.second.IsNull()); } } else if ((flags & kVisitRootFlagNewRoots) != 0) { for (auto& pair : new_strong_intern_roots_) { - mirror::String* old_ref = pair.second; - callback(reinterpret_cast<mirror::Object**>(&pair.second), arg, 0, kRootInternedString); - if (UNLIKELY(pair.second != old_ref)) { - // Uh ohes, GC moved a root in the log. Need to search the strong interns and update the - // corresponding object. This is slow, but luckily for us, this may only happen with a - // concurrent moving GC. - for (auto it = strong_interns_.lower_bound(pair.first), end = strong_interns_.end(); + mirror::String* old_ref = pair.second.Read<kWithoutReadBarrier>(); + pair.second.VisitRoot(callback, arg, 0, kRootInternedString); + mirror::String* new_ref = pair.second.Read<kWithoutReadBarrier>(); + if (UNLIKELY(new_ref != old_ref)) { + // Uh ohes, GC moved a root in the log. Need to search the strong interns and update the + // corresponding object. This is slow, but luckily for us, this may only happen with a + // concurrent moving GC. + for (auto it = strong_interns_.lower_bound(pair.first), end = strong_interns_.end(); it != end && it->first == pair.first; ++it) { - // If the class stored matches the old class, update it to the new value. - if (old_ref == it->second) { - it->second = pair.second; - } - } - } - } + // If the class stored matches the old class, update it to the new value. + if (old_ref == it->second.Read<kWithoutReadBarrier>()) { + it->second = GcRoot<mirror::String>(new_ref); + } + } + } + } } if ((flags & kVisitRootFlagClearRootLog) != 0) { @@ -105,9 +105,7 @@ mirror::String* InternTable::Lookup(Table* table, mirror::String* s, int32_t has Locks::intern_table_lock_->AssertHeld(Thread::Current()); for (auto it = table->lower_bound(hash_code), end = table->end(); it != end && it->first == hash_code; ++it) { - mirror::String* existing_string; - mirror::String** root = &it->second; - existing_string = ReadBarrier::BarrierForRoot<mirror::String, kWithReadBarrier>(root); + mirror::String* existing_string = it->second.Read(); if (existing_string->Equals(s)) { return existing_string; } @@ -121,9 +119,9 @@ mirror::String* InternTable::InsertStrong(mirror::String* s, int32_t hash_code) runtime->RecordStrongStringInsertion(s, hash_code); } if (log_new_roots_) { - new_strong_intern_roots_.push_back(std::make_pair(hash_code, s)); + new_strong_intern_roots_.push_back(std::make_pair(hash_code, GcRoot<mirror::String>(s))); } - strong_interns_.insert(std::make_pair(hash_code, s)); + strong_interns_.insert(std::make_pair(hash_code, GcRoot<mirror::String>(s))); return s; } @@ -132,7 +130,7 @@ mirror::String* InternTable::InsertWeak(mirror::String* s, int32_t hash_code) { if (runtime->IsActiveTransaction()) { runtime->RecordWeakStringInsertion(s, hash_code); } - weak_interns_.insert(std::make_pair(hash_code, s)); + weak_interns_.insert(std::make_pair(hash_code, GcRoot<mirror::String>(s))); return s; } @@ -151,9 +149,7 @@ void InternTable::RemoveWeak(mirror::String* s, int32_t hash_code) { void InternTable::Remove(Table* table, mirror::String* s, int32_t hash_code) { for (auto it = table->lower_bound(hash_code), end = table->end(); it != end && it->first == hash_code; ++it) { - mirror::String* existing_string; - mirror::String** root = &it->second; - existing_string = ReadBarrier::BarrierForRoot<mirror::String, kWithReadBarrier>(root); + mirror::String* existing_string = it->second.Read(); if (existing_string == s) { table->erase(it); return; @@ -308,13 +304,13 @@ void InternTable::SweepInternTableWeaks(IsMarkedCallback* callback, void* arg) { MutexLock mu(Thread::Current(), *Locks::intern_table_lock_); for (auto it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) { // This does not need a read barrier because this is called by GC. - mirror::Object* object = it->second; + mirror::Object* object = it->second.Read<kWithoutReadBarrier>(); mirror::Object* new_object = callback(object, arg); if (new_object == nullptr) { // TODO: use it = weak_interns_.erase(it) when we get a c++11 stl. weak_interns_.erase(it++); } else { - it->second = down_cast<mirror::String*>(new_object); + it->second = GcRoot<mirror::String>(down_cast<mirror::String*>(new_object)); ++it; } } diff --git a/runtime/intern_table.h b/runtime/intern_table.h index 6dc7f7b606..435cc430b1 100644 --- a/runtime/intern_table.h +++ b/runtime/intern_table.h @@ -20,6 +20,7 @@ #include <map> #include "base/mutex.h" +#include "gc_root.h" #include "object_callbacks.h" namespace art { @@ -59,7 +60,8 @@ class InternTable { // Interns a potentially new string in the 'weak' table. (See above.) mirror::String* InternWeak(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SweepInternTableWeaks(IsMarkedCallback* callback, void* arg); + void SweepInternTableWeaks(IsMarkedCallback* callback, void* arg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool ContainsWeak(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -67,7 +69,8 @@ class InternTable { size_t StrongSize() const; size_t WeakSize() const; - void VisitRoots(RootCallback* callback, void* arg, VisitRootFlags flags); + void VisitRoots(RootCallback* callback, void* arg, VisitRootFlags flags) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void DumpForSigQuit(std::ostream& os) const; @@ -75,7 +78,7 @@ class InternTable { void AllowNewInterns() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); private: - typedef std::multimap<int32_t, mirror::String*> Table; + typedef std::multimap<int32_t, GcRoot<mirror::String>> Table; mirror::String* Insert(mirror::String* s, bool is_strong) LOCKS_EXCLUDED(Locks::intern_table_lock_) @@ -122,7 +125,7 @@ class InternTable { // directly access the strings in it. Use functions that contain // read barriers. Table strong_interns_ GUARDED_BY(Locks::intern_table_lock_); - std::vector<std::pair<int32_t, mirror::String*>> new_strong_intern_roots_ + std::vector<std::pair<int32_t, GcRoot<mirror::String>>> new_strong_intern_roots_ GUARDED_BY(Locks::intern_table_lock_); // Since this contains (weak) roots, they need a read barrier. Do // not directly access the strings in it. Use functions that contain diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 64cca3d2f2..d5b90f2cfe 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -29,6 +29,7 @@ #include "base/stl_util.h" #include "class_linker-inl.h" #include "dex_file-inl.h" +#include "gc_root.h" #include "gc/accounting/card_table-inl.h" #include "indirect_reference_table-inl.h" #include "interpreter/interpreter.h" @@ -364,7 +365,7 @@ class SharedLibrary { : path_(path), handle_(handle), needs_native_bridge_(false), - class_loader_(class_loader), + class_loader_(GcRoot<mirror::Object>(class_loader)), jni_on_load_lock_("JNI_OnLoad lock"), jni_on_load_cond_("JNI_OnLoad condition variable", jni_on_load_lock_), jni_on_load_thread_id_(Thread::Current()->GetThreadId()), @@ -372,8 +373,7 @@ class SharedLibrary { } mirror::Object* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object** root = &class_loader_; - return ReadBarrier::BarrierForRoot<mirror::Object, kWithReadBarrier>(root); + return class_loader_.Read(); } std::string GetPath() { @@ -449,8 +449,8 @@ class SharedLibrary { } void VisitRoots(RootCallback* visitor, void* arg) { - if (class_loader_ != nullptr) { - visitor(&class_loader_, arg, 0, kRootVMInternal); + if (!class_loader_.IsNull()) { + class_loader_.VisitRoot(visitor, arg, 0, kRootVMInternal); } } @@ -471,7 +471,7 @@ class SharedLibrary { bool needs_native_bridge_; // The ClassLoader this library is associated with. - mirror::Object* class_loader_; + GcRoot<mirror::Object> class_loader_; // Guards remaining items. Mutex jni_on_load_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; diff --git a/runtime/jni_internal.h b/runtime/jni_internal.h index abb71b7fbf..ac502e6f0b 100644 --- a/runtime/jni_internal.h +++ b/runtime/jni_internal.h @@ -85,7 +85,8 @@ class JavaVMExt : public JavaVM { void SetCheckJniEnabled(bool enabled); - void VisitRoots(RootCallback* callback, void* arg); + void VisitRoots(RootCallback* callback, void* arg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void DisallowNewWeakGlobals() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_); void AllowNewWeakGlobals() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -93,7 +94,8 @@ class JavaVMExt : public JavaVM { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void DeleteWeakGlobalRef(Thread* self, jweak obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SweepJniWeakGlobals(IsMarkedCallback* callback, void* arg); + void SweepJniWeakGlobals(IsMarkedCallback* callback, void* arg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::Object* DecodeWeakGlobal(Thread* self, IndirectRef ref) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h index f3c8250db3..2c0ea367cc 100644 --- a/runtime/mirror/array-inl.h +++ b/runtime/mirror/array-inl.h @@ -166,8 +166,8 @@ inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_c template<class T> inline void PrimitiveArray<T>::VisitRoots(RootCallback* callback, void* arg) { - if (array_class_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&array_class_), arg, 0, kRootStickyClass); + if (!array_class_.IsNull()) { + array_class_.VisitRoot(callback, arg, 0, kRootStickyClass); } } diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc index 63f9860278..f54af855b4 100644 --- a/runtime/mirror/array.cc +++ b/runtime/mirror/array.cc @@ -124,7 +124,7 @@ void Array::ThrowArrayStoreException(Object* object) { art::ThrowArrayStoreException(object->GetClass(), this->GetClass()); } -template <typename T> Class* PrimitiveArray<T>::array_class_ = NULL; +template <typename T> GcRoot<Class> PrimitiveArray<T>::array_class_; // Explicitly instantiate all the primitive array types. template class PrimitiveArray<uint8_t>; // BooleanArray diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h index 6588b57b8a..7af88d6d86 100644 --- a/runtime/mirror/array.h +++ b/runtime/mirror/array.h @@ -17,10 +17,10 @@ #ifndef ART_RUNTIME_MIRROR_ARRAY_H_ #define ART_RUNTIME_MIRROR_ARRAY_H_ +#include "gc_root.h" #include "gc/allocator_type.h" #include "object.h" #include "object_callbacks.h" -#include "read_barrier.h" namespace art { @@ -159,27 +159,26 @@ class MANAGED PrimitiveArray : public Array { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void SetArrayClass(Class* array_class) { - CHECK(array_class_ == nullptr); + CHECK(array_class_.IsNull()); CHECK(array_class != nullptr); - array_class_ = array_class; + array_class_ = GcRoot<Class>(array_class); } static Class* GetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(array_class_ != nullptr); - return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>( - &array_class_); + DCHECK(!array_class_.IsNull()); + return array_class_.Read(); } static void ResetArrayClass() { - CHECK(array_class_ != nullptr); - array_class_ = nullptr; + CHECK(!array_class_.IsNull()); + array_class_ = GcRoot<Class>(nullptr); } static void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); private: - static Class* array_class_; + static GcRoot<Class> array_class_; DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray); }; diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc index da21dfef06..3c7c6ce39a 100644 --- a/runtime/mirror/art_field.cc +++ b/runtime/mirror/art_field.cc @@ -29,7 +29,7 @@ namespace art { namespace mirror { // TODO: Get global references for these -Class* ArtField::java_lang_reflect_ArtField_ = NULL; +GcRoot<Class> ArtField::java_lang_reflect_ArtField_; ArtField* ArtField::FromReflectedField(const ScopedObjectAccessAlreadyRunnable& soa, jobject jlr_field) { @@ -40,14 +40,14 @@ ArtField* ArtField::FromReflectedField(const ScopedObjectAccessAlreadyRunnable& } void ArtField::SetClass(Class* java_lang_reflect_ArtField) { - CHECK(java_lang_reflect_ArtField_ == NULL); + CHECK(java_lang_reflect_ArtField_.IsNull()); CHECK(java_lang_reflect_ArtField != NULL); - java_lang_reflect_ArtField_ = java_lang_reflect_ArtField; + java_lang_reflect_ArtField_ = GcRoot<Class>(java_lang_reflect_ArtField); } void ArtField::ResetClass() { - CHECK(java_lang_reflect_ArtField_ != NULL); - java_lang_reflect_ArtField_ = NULL; + CHECK(!java_lang_reflect_ArtField_.IsNull()); + java_lang_reflect_ArtField_ = GcRoot<Class>(nullptr); } void ArtField::SetOffset(MemberOffset num_bytes) { @@ -64,9 +64,8 @@ void ArtField::SetOffset(MemberOffset num_bytes) { } void ArtField::VisitRoots(RootCallback* callback, void* arg) { - if (java_lang_reflect_ArtField_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&java_lang_reflect_ArtField_), arg, 0, - kRootStickyClass); + if (!java_lang_reflect_ArtField_.IsNull()) { + java_lang_reflect_ArtField_.VisitRoot(callback, arg, 0, kRootStickyClass); } } diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h index 741c6eb8a8..f3dfa15004 100644 --- a/runtime/mirror/art_field.h +++ b/runtime/mirror/art_field.h @@ -19,11 +19,12 @@ #include <jni.h> +#include "gc_root.h" #include "modifiers.h" #include "object.h" #include "object_callbacks.h" #include "primitive.h" -#include "read_barrier.h" +#include "read_barrier_option.h" namespace art { @@ -135,9 +136,8 @@ class MANAGED ArtField FINAL : public Object { template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> static Class* GetJavaLangReflectArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(java_lang_reflect_ArtField_ != nullptr); - return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>( - &java_lang_reflect_ArtField_); + DCHECK(!java_lang_reflect_ArtField_.IsNull()); + return java_lang_reflect_ArtField_.Read<kReadBarrierOption>(); } static void SetClass(Class* java_lang_reflect_ArtField); @@ -180,7 +180,7 @@ class MANAGED ArtField FINAL : public Object { // Offset of field within an instance or in the Class' static fields uint32_t offset_; - static Class* java_lang_reflect_ArtField_; + static GcRoot<Class> java_lang_reflect_ArtField_; friend struct art::ArtFieldOffsets; // for verifying offset information DISALLOW_IMPLICIT_CONSTRUCTORS(ArtField); diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h index 01b05a6e6f..73de683a12 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -41,9 +41,8 @@ inline uint32_t ArtMethod::ClassSize() { template<ReadBarrierOption kReadBarrierOption> inline Class* ArtMethod::GetJavaLangReflectArtMethod() { - DCHECK(java_lang_reflect_ArtMethod_ != nullptr); - return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>( - &java_lang_reflect_ArtMethod_); + DCHECK(!java_lang_reflect_ArtMethod_.IsNull()); + return java_lang_reflect_ArtMethod_.Read<kReadBarrierOption>(); } inline Class* ArtMethod::GetDeclaringClass() { diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index 211ba1dde2..4882728e0d 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -47,7 +47,7 @@ extern "C" void art_quick_invoke_static_stub(ArtMethod*, uint32_t*, uint32_t, Th #endif // TODO: get global references for these -Class* ArtMethod::java_lang_reflect_ArtMethod_ = NULL; +GcRoot<Class> ArtMethod::java_lang_reflect_ArtMethod_; ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject jlr_method) { @@ -60,9 +60,8 @@ ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnabl void ArtMethod::VisitRoots(RootCallback* callback, void* arg) { - if (java_lang_reflect_ArtMethod_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&java_lang_reflect_ArtMethod_), arg, 0, - kRootStickyClass); + if (!java_lang_reflect_ArtMethod_.IsNull()) { + java_lang_reflect_ArtMethod_.VisitRoot(callback, arg, 0, kRootStickyClass); } } @@ -80,14 +79,14 @@ InvokeType ArtMethod::GetInvokeType() { } void ArtMethod::SetClass(Class* java_lang_reflect_ArtMethod) { - CHECK(java_lang_reflect_ArtMethod_ == NULL); + CHECK(java_lang_reflect_ArtMethod_.IsNull()); CHECK(java_lang_reflect_ArtMethod != NULL); - java_lang_reflect_ArtMethod_ = java_lang_reflect_ArtMethod; + java_lang_reflect_ArtMethod_ = GcRoot<Class>(java_lang_reflect_ArtMethod); } void ArtMethod::ResetClass() { - CHECK(java_lang_reflect_ArtMethod_ != NULL); - java_lang_reflect_ArtMethod_ = NULL; + CHECK(!java_lang_reflect_ArtMethod_.IsNull()); + java_lang_reflect_ArtMethod_ = GcRoot<Class>(nullptr); } void ArtMethod::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) { diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index 081bee1d88..01e6149e23 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_MIRROR_ART_METHOD_H_ #include "dex_file.h" +#include "gc_root.h" #include "invoke_type.h" #include "modifiers.h" #include "object.h" @@ -514,7 +515,7 @@ class MANAGED ArtMethod FINAL : public Object { // ifTable. uint32_t method_index_; - static Class* java_lang_reflect_ArtMethod_; + static GcRoot<Class> java_lang_reflect_ArtMethod_; private: friend struct art::ArtMethodOffsets; // for verifying offset information diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index a218b1cf5f..f29ba73d56 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -36,24 +36,24 @@ namespace art { namespace mirror { -Class* Class::java_lang_Class_ = nullptr; +GcRoot<Class> Class::java_lang_Class_; void Class::SetClassClass(Class* java_lang_Class) { - CHECK(java_lang_Class_ == nullptr) - << ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>(&java_lang_Class_) + CHECK(java_lang_Class_.IsNull()) + << java_lang_Class_.Read() << " " << java_lang_Class; CHECK(java_lang_Class != nullptr); - java_lang_Class_ = java_lang_Class; + java_lang_Class_ = GcRoot<Class>(java_lang_Class); } void Class::ResetClass() { - CHECK(java_lang_Class_ != nullptr); - java_lang_Class_ = nullptr; + CHECK(!java_lang_Class_.IsNull()); + java_lang_Class_ = GcRoot<Class>(nullptr); } void Class::VisitRoots(RootCallback* callback, void* arg) { - if (java_lang_Class_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&java_lang_Class_), arg, 0, kRootStickyClass); + if (!java_lang_Class_.IsNull()) { + java_lang_Class_.VisitRoot(callback, arg, 0, kRootStickyClass); } } @@ -879,8 +879,9 @@ Class* Class::CopyOf(Thread* self, int32_t new_length) { CopyClassVisitor visitor(self, &h_this, new_length, sizeof(Class)); mirror::Object* new_class = - kMovingClasses ? heap->AllocObject<true>(self, java_lang_Class_, new_length, visitor) - : heap->AllocNonMovableObject<true>(self, java_lang_Class_, new_length, visitor); + kMovingClasses + ? heap->AllocObject<true>(self, java_lang_Class_.Read(), new_length, visitor) + : heap->AllocNonMovableObject<true>(self, java_lang_Class_.Read(), new_length, visitor); if (UNLIKELY(new_class == nullptr)) { CHECK(self->IsExceptionPending()); // Expect an OOME. return NULL; diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 0525abf27a..1e254fad61 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_MIRROR_CLASS_H_ #include "dex_file.h" +#include "gc_root.h" #include "gc/allocator_type.h" #include "invoke_type.h" #include "modifiers.h" @@ -25,7 +26,7 @@ #include "object_array.h" #include "object_callbacks.h" #include "primitive.h" -#include "read_barrier.h" +#include "read_barrier_option.h" /* * A magic value for refOffsets. Ignore the bits and walk the super @@ -936,9 +937,8 @@ class MANAGED Class FINAL : public Object { } static Class* GetJavaLangClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(java_lang_Class_ != NULL); - return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>( - &java_lang_Class_); + DCHECK(!java_lang_Class_.IsNull()); + return java_lang_Class_.Read(); } // Can't call this SetClass or else gets called instead of Object::SetClass in places. @@ -1156,7 +1156,7 @@ class MANAGED Class FINAL : public Object { uint32_t fields_[0]; // java.lang.Class - static Class* java_lang_Class_; + static GcRoot<Class> java_lang_Class_; friend struct art::ClassOffsets; // for verifying offset information DISALLOW_IMPLICIT_CONSTRUCTORS(Class); diff --git a/runtime/mirror/reference.cc b/runtime/mirror/reference.cc index 077cd4b913..c36bd980f9 100644 --- a/runtime/mirror/reference.cc +++ b/runtime/mirror/reference.cc @@ -19,23 +19,22 @@ namespace art { namespace mirror { -Class* Reference::java_lang_ref_Reference_ = nullptr; +GcRoot<Class> Reference::java_lang_ref_Reference_; void Reference::SetClass(Class* java_lang_ref_Reference) { - CHECK(java_lang_ref_Reference_ == nullptr); + CHECK(java_lang_ref_Reference_.IsNull()); CHECK(java_lang_ref_Reference != nullptr); - java_lang_ref_Reference_ = java_lang_ref_Reference; + java_lang_ref_Reference_ = GcRoot<Class>(java_lang_ref_Reference); } void Reference::ResetClass() { - CHECK(java_lang_ref_Reference_ != nullptr); - java_lang_ref_Reference_ = nullptr; + CHECK(!java_lang_ref_Reference_.IsNull()); + java_lang_ref_Reference_ = GcRoot<Class>(nullptr); } void Reference::VisitRoots(RootCallback* callback, void* arg) { - if (java_lang_ref_Reference_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&java_lang_ref_Reference_), - arg, 0, kRootStickyClass); + if (!java_lang_ref_Reference_.IsNull()) { + java_lang_ref_Reference_.VisitRoot(callback, arg, 0, kRootStickyClass); } } diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h index 07d47d31e7..7345448ed7 100644 --- a/runtime/mirror/reference.h +++ b/runtime/mirror/reference.h @@ -18,9 +18,10 @@ #define ART_RUNTIME_MIRROR_REFERENCE_H_ #include "class.h" +#include "gc_root.h" #include "object.h" #include "object_callbacks.h" -#include "read_barrier.h" +#include "read_barrier_option.h" #include "thread.h" namespace art { @@ -94,9 +95,8 @@ class MANAGED Reference : public Object { template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> static Class* GetJavaLangRefReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(java_lang_ref_Reference_ != nullptr); - return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>( - &java_lang_ref_Reference_); + DCHECK(!java_lang_ref_Reference_.IsNull()); + return java_lang_ref_Reference_.Read<kReadBarrierOption>(); } static void SetClass(Class* klass); static void ResetClass(void); @@ -114,7 +114,7 @@ class MANAGED Reference : public Object { HeapReference<Reference> queue_next_; // Note this is Java volatile: HeapReference<Object> referent_; // Note this is Java volatile: - static Class* java_lang_ref_Reference_; + static GcRoot<Class> java_lang_ref_Reference_; friend struct art::ReferenceOffsets; // for verifying offset information friend class gc::ReferenceProcessor; diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc index b1de2b6f7d..1eb20f71a6 100644 --- a/runtime/mirror/stack_trace_element.cc +++ b/runtime/mirror/stack_trace_element.cc @@ -26,17 +26,17 @@ namespace art { namespace mirror { -Class* StackTraceElement::java_lang_StackTraceElement_ = NULL; +GcRoot<Class> StackTraceElement::java_lang_StackTraceElement_; void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) { - CHECK(java_lang_StackTraceElement_ == NULL); + CHECK(java_lang_StackTraceElement_.IsNull()); CHECK(java_lang_StackTraceElement != NULL); - java_lang_StackTraceElement_ = java_lang_StackTraceElement; + java_lang_StackTraceElement_ = GcRoot<Class>(java_lang_StackTraceElement); } void StackTraceElement::ResetClass() { - CHECK(java_lang_StackTraceElement_ != NULL); - java_lang_StackTraceElement_ = NULL; + CHECK(!java_lang_StackTraceElement_.IsNull()); + java_lang_StackTraceElement_ = GcRoot<Class>(nullptr); } StackTraceElement* StackTraceElement::Alloc(Thread* self, Handle<String> declaring_class, @@ -68,9 +68,8 @@ void StackTraceElement::Init(Handle<String> declaring_class, Handle<String> meth } void StackTraceElement::VisitRoots(RootCallback* callback, void* arg) { - if (java_lang_StackTraceElement_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&java_lang_StackTraceElement_), arg, 0, - kRootStickyClass); + if (!java_lang_StackTraceElement_.IsNull()) { + java_lang_StackTraceElement_.VisitRoot(callback, arg, 0, kRootStickyClass); } } diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h index 52b0927756..70acd1ce55 100644 --- a/runtime/mirror/stack_trace_element.h +++ b/runtime/mirror/stack_trace_element.h @@ -17,9 +17,9 @@ #ifndef ART_RUNTIME_MIRROR_STACK_TRACE_ELEMENT_H_ #define ART_RUNTIME_MIRROR_STACK_TRACE_ELEMENT_H_ +#include "gc_root.h" #include "object.h" #include "object_callbacks.h" -#include "read_barrier.h" namespace art { @@ -57,9 +57,8 @@ class MANAGED StackTraceElement FINAL : public Object { static void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static Class* GetStackTraceElement() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(java_lang_StackTraceElement_ != NULL); - return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>( - &java_lang_StackTraceElement_); + DCHECK(!java_lang_StackTraceElement_.IsNull()); + return java_lang_StackTraceElement_.Read(); } private: @@ -74,7 +73,7 @@ class MANAGED StackTraceElement FINAL : public Object { int32_t line_number) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static Class* java_lang_StackTraceElement_; + static GcRoot<Class> java_lang_StackTraceElement_; friend struct art::StackTraceElementOffsets; // for verifying offset information DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement); diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc index 5c57dcef45..e81e4312e7 100644 --- a/runtime/mirror/string.cc +++ b/runtime/mirror/string.cc @@ -31,7 +31,7 @@ namespace art { namespace mirror { // TODO: get global references for these -Class* String::java_lang_String_ = NULL; +GcRoot<Class> String::java_lang_String_; int32_t String::FastIndexOf(int32_t ch, int32_t start) { int32_t count = GetLength(); @@ -52,14 +52,14 @@ int32_t String::FastIndexOf(int32_t ch, int32_t start) { } void String::SetClass(Class* java_lang_String) { - CHECK(java_lang_String_ == NULL); + CHECK(java_lang_String_.IsNull()); CHECK(java_lang_String != NULL); - java_lang_String_ = java_lang_String; + java_lang_String_ = GcRoot<Class>(java_lang_String); } void String::ResetClass() { - CHECK(java_lang_String_ != NULL); - java_lang_String_ = NULL; + CHECK(!java_lang_String_.IsNull()); + java_lang_String_ = GcRoot<Class>(nullptr); } int32_t String::GetHashCode() { @@ -233,8 +233,8 @@ int32_t String::CompareTo(String* rhs) { } void String::VisitRoots(RootCallback* callback, void* arg) { - if (java_lang_String_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&java_lang_String_), arg, 0, kRootStickyClass); + if (!java_lang_String_.IsNull()) { + java_lang_String_.VisitRoot(callback, arg, 0, kRootStickyClass); } } diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h index 46bdd59b5c..66a5dd827d 100644 --- a/runtime/mirror/string.h +++ b/runtime/mirror/string.h @@ -19,9 +19,9 @@ #include <gtest/gtest.h> +#include "gc_root.h" #include "object.h" #include "object_callbacks.h" -#include "read_barrier.h" namespace art { @@ -111,9 +111,8 @@ class MANAGED String FINAL : public Object { int32_t CompareTo(String* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static Class* GetJavaLangString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(java_lang_String_ != NULL); - return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>( - &java_lang_String_); + DCHECK(!java_lang_String_.IsNull()); + return java_lang_String_.Read(); } static void SetClass(Class* java_lang_String); @@ -160,7 +159,7 @@ class MANAGED String FINAL : public Object { int32_t offset_; - static Class* java_lang_String_; + static GcRoot<Class> java_lang_String_; friend struct art::StringOffsets; // for verifying offset information FRIEND_TEST(ObjectTest, StringLength); // for SetOffset and SetCount diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc index 1c3f1ed5bf..93ed4d4daf 100644 --- a/runtime/mirror/throwable.cc +++ b/runtime/mirror/throwable.cc @@ -30,7 +30,7 @@ namespace art { namespace mirror { -Class* Throwable::java_lang_Throwable_ = NULL; +GcRoot<Class> Throwable::java_lang_Throwable_; void Throwable::SetDetailMessage(String* new_detail_message) { if (Runtime::Current()->IsActiveTransaction()) { @@ -127,19 +127,19 @@ std::string Throwable::Dump() { } void Throwable::SetClass(Class* java_lang_Throwable) { - CHECK(java_lang_Throwable_ == NULL); + CHECK(java_lang_Throwable_.IsNull()); CHECK(java_lang_Throwable != NULL); - java_lang_Throwable_ = java_lang_Throwable; + java_lang_Throwable_ = GcRoot<Class>(java_lang_Throwable); } void Throwable::ResetClass() { - CHECK(java_lang_Throwable_ != NULL); - java_lang_Throwable_ = NULL; + CHECK(!java_lang_Throwable_.IsNull()); + java_lang_Throwable_ = GcRoot<Class>(nullptr); } void Throwable::VisitRoots(RootCallback* callback, void* arg) { - if (java_lang_Throwable_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&java_lang_Throwable_), arg, 0, kRootStickyClass); + if (!java_lang_Throwable_.IsNull()) { + java_lang_Throwable_.VisitRoot(callback, arg, 0, kRootStickyClass); } } diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h index cf54ad69a9..f90812d2ec 100644 --- a/runtime/mirror/throwable.h +++ b/runtime/mirror/throwable.h @@ -17,9 +17,9 @@ #ifndef ART_RUNTIME_MIRROR_THROWABLE_H_ #define ART_RUNTIME_MIRROR_THROWABLE_H_ +#include "gc_root.h" #include "object.h" #include "object_callbacks.h" -#include "read_barrier.h" #include "string.h" namespace art { @@ -47,9 +47,8 @@ class MANAGED Throwable : public Object { bool IsCheckedException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static Class* GetJavaLangThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(java_lang_Throwable_ != NULL); - return ReadBarrier::BarrierForRoot<mirror::Class, kWithReadBarrier>( - &java_lang_Throwable_); + DCHECK(!java_lang_Throwable_.IsNull()); + return java_lang_Throwable_.Read(); } static void SetClass(Class* java_lang_Throwable); @@ -72,7 +71,7 @@ class MANAGED Throwable : public Object { HeapReference<Object> stack_trace_; HeapReference<Object> suppressed_exceptions_; - static Class* java_lang_Throwable_; + static GcRoot<Class> java_lang_Throwable_; friend struct art::ThrowableOffsets; // for verifying offset information DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable); diff --git a/runtime/monitor.cc b/runtime/monitor.cc index 371a9d9dd6..433c1b2d6d 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -84,7 +84,7 @@ Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_ num_waiters_(0), owner_(owner), lock_count_(0), - obj_(obj), + obj_(GcRoot<mirror::Object>(obj)), wait_set_(NULL), hash_code_(hash_code), locking_method_(NULL), @@ -107,7 +107,7 @@ Monitor::Monitor(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_ num_waiters_(0), owner_(owner), lock_count_(0), - obj_(obj), + obj_(GcRoot<mirror::Object>(obj)), wait_set_(NULL), hash_code_(hash_code), locking_method_(NULL), @@ -225,7 +225,7 @@ void Monitor::RemoveFromWaitSet(Thread *thread) { } void Monitor::SetObject(mirror::Object* object) { - obj_ = object; + obj_ = GcRoot<mirror::Object>(object); } void Monitor::Lock(Thread* self) { @@ -636,7 +636,7 @@ bool Monitor::Deflate(Thread* self, mirror::Object* obj) { } // The monitor is deflated, mark the object as nullptr so that we know to delete it during the // next GC. - monitor->obj_ = nullptr; + monitor->obj_ = GcRoot<mirror::Object>(nullptr); } return true; } diff --git a/runtime/monitor.h b/runtime/monitor.h index 0d0ad0b13d..26d43c953b 100644 --- a/runtime/monitor.h +++ b/runtime/monitor.h @@ -26,8 +26,9 @@ #include "atomic.h" #include "base/mutex.h" +#include "gc_root.h" #include "object_callbacks.h" -#include "read_barrier.h" +#include "read_barrier_option.h" #include "thread_state.h" namespace art { @@ -95,7 +96,7 @@ class Monitor { template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> mirror::Object* GetObject() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ReadBarrier::BarrierForRoot<mirror::Object, kReadBarrierOption>(&obj_); + return obj_.Read<kReadBarrierOption>(); } void SetObject(mirror::Object* object); @@ -197,7 +198,7 @@ class Monitor { // What object are we part of. This is a weak root. Do not access // this directly, use GetObject() to read it so it will be guarded // by a read barrier. - mirror::Object* obj_; + GcRoot<mirror::Object> obj_; // Threads currently waiting on this monitor. Thread* wait_set_ GUARDED_BY(monitor_lock_); diff --git a/runtime/reference_table.cc b/runtime/reference_table.cc index cd35863543..70aba9bbf1 100644 --- a/runtime/reference_table.cc +++ b/runtime/reference_table.cc @@ -24,7 +24,6 @@ #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "mirror/string-inl.h" -#include "read_barrier.h" #include "thread.h" #include "utils.h" @@ -46,14 +45,13 @@ void ReferenceTable::Add(mirror::Object* obj) { LOG(FATAL) << "ReferenceTable '" << name_ << "' " << "overflowed (" << max_size_ << " entries)"; } - entries_.push_back(obj); + entries_.push_back(GcRoot<mirror::Object>(obj)); } void ReferenceTable::Remove(mirror::Object* obj) { // We iterate backwards on the assumption that references are LIFO. for (int i = entries_.size() - 1; i >= 0; --i) { - mirror::Object* entry = - ReadBarrier::BarrierForRoot<mirror::Object, kWithReadBarrier>(&entries_[i]); + mirror::Object* entry = entries_[i].Read(); if (entry == obj) { entries_.erase(entries_.begin() + i); return; @@ -71,10 +69,12 @@ static size_t GetElementCount(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks:: } struct ObjectComparator { - bool operator()(mirror::Object* obj1, mirror::Object* obj2) + bool operator()(GcRoot<mirror::Object> root1, GcRoot<mirror::Object> root2) // TODO: enable analysis when analysis can work with the STL. NO_THREAD_SAFETY_ANALYSIS { Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); + mirror::Object* obj1 = root1.Read<kWithoutReadBarrier>(); + mirror::Object* obj2 = root2.Read<kWithoutReadBarrier>(); // Ensure null references and cleared jweaks appear at the end. if (obj1 == NULL) { return true; @@ -163,8 +163,7 @@ void ReferenceTable::Dump(std::ostream& os, Table& entries) { } os << " Last " << (count - first) << " entries (of " << count << "):\n"; for (int idx = count - 1; idx >= first; --idx) { - mirror::Object* ref = - ReadBarrier::BarrierForRoot<mirror::Object, kWithReadBarrier>(&entries[idx]); + mirror::Object* ref = entries[idx].Read(); if (ref == NULL) { continue; } @@ -200,17 +199,17 @@ void ReferenceTable::Dump(std::ostream& os, Table& entries) { // Make a copy of the table and sort it. Table sorted_entries; for (size_t i = 0; i < entries.size(); ++i) { - mirror::Object* entry = - ReadBarrier::BarrierForRoot<mirror::Object, kWithReadBarrier>(&entries[i]); - sorted_entries.push_back(entry); + mirror::Object* entry = entries[i].Read(); + sorted_entries.push_back(GcRoot<mirror::Object>(entry)); } std::sort(sorted_entries.begin(), sorted_entries.end(), ObjectComparator()); // Remove any uninteresting stuff from the list. The sort moved them all to the end. - while (!sorted_entries.empty() && sorted_entries.back() == NULL) { + while (!sorted_entries.empty() && sorted_entries.back().IsNull()) { sorted_entries.pop_back(); } - while (!sorted_entries.empty() && sorted_entries.back() == kClearedJniWeakGlobal) { + while (!sorted_entries.empty() && + sorted_entries.back().Read<kWithoutReadBarrier>() == kClearedJniWeakGlobal) { sorted_entries.pop_back(); } if (sorted_entries.empty()) { @@ -222,8 +221,8 @@ void ReferenceTable::Dump(std::ostream& os, Table& entries) { size_t equiv = 0; size_t identical = 0; for (size_t idx = 1; idx < count; idx++) { - mirror::Object* prev = sorted_entries[idx-1]; - mirror::Object* current = sorted_entries[idx]; + mirror::Object* prev = sorted_entries[idx-1].Read<kWithoutReadBarrier>(); + mirror::Object* current = sorted_entries[idx].Read<kWithoutReadBarrier>(); size_t element_count = GetElementCount(prev); if (current == prev) { // Same reference, added more than once. @@ -238,13 +237,15 @@ void ReferenceTable::Dump(std::ostream& os, Table& entries) { } } // Handle the last entry. - DumpSummaryLine(os, sorted_entries.back(), GetElementCount(sorted_entries.back()), identical, equiv); + DumpSummaryLine(os, sorted_entries.back().Read<kWithoutReadBarrier>(), + GetElementCount(sorted_entries.back().Read<kWithoutReadBarrier>()), + identical, equiv); } void ReferenceTable::VisitRoots(RootCallback* visitor, void* arg, uint32_t tid, RootType root_type) { - for (auto& ref : entries_) { - visitor(&ref, arg, tid, root_type); + for (GcRoot<mirror::Object>& root : entries_) { + root.VisitRoot(visitor, arg, tid, root_type); } } diff --git a/runtime/reference_table.h b/runtime/reference_table.h index 1cd0999f26..876544238a 100644 --- a/runtime/reference_table.h +++ b/runtime/reference_table.h @@ -23,6 +23,7 @@ #include <vector> #include "base/mutex.h" +#include "gc_root.h" #include "object_callbacks.h" namespace art { @@ -50,7 +51,7 @@ class ReferenceTable { void VisitRoots(RootCallback* visitor, void* arg, uint32_t tid, RootType root_type); private: - typedef std::vector<mirror::Object*> Table; + typedef std::vector<GcRoot<mirror::Object>> Table; static void Dump(std::ostream& os, Table& entries) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); friend class IndirectReferenceTable; // For Dump. diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h index f776bcd336..ac9026b605 100644 --- a/runtime/runtime-inl.h +++ b/runtime/runtime-inl.h @@ -41,32 +41,29 @@ inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(mirror::ArtMethod inline mirror::ArtMethod* Runtime::GetResolutionMethod() { CHECK(HasResolutionMethod()); - return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&resolution_method_); + return resolution_method_.Read(); } inline mirror::ArtMethod* Runtime::GetImtConflictMethod() { CHECK(HasImtConflictMethod()); - return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&imt_conflict_method_); + return imt_conflict_method_.Read(); } inline mirror::ObjectArray<mirror::ArtMethod>* Runtime::GetDefaultImt() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(HasDefaultImt()); - return ReadBarrier::BarrierForRoot<mirror::ObjectArray<mirror::ArtMethod>, kWithReadBarrier>( - &default_imt_); + return default_imt_.Read(); } inline mirror::ArtMethod* Runtime::GetCalleeSaveMethod(CalleeSaveType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(HasCalleeSaveMethod(type)); - return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>( - &callee_save_methods_[type]); + return callee_save_methods_[type].Read(); } inline mirror::ArtMethod* Runtime::GetCalleeSaveMethodUnchecked(CalleeSaveType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>( - &callee_save_methods_[type]); + return callee_save_methods_[type].Read(); } } // namespace art diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 1cbf841dfd..e34a2d7365 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -95,11 +95,7 @@ const char* Runtime::kDefaultInstructionSetFeatures = Runtime* Runtime::instance_ = NULL; Runtime::Runtime() - : pre_allocated_OutOfMemoryError_(nullptr), - resolution_method_(nullptr), - imt_conflict_method_(nullptr), - default_imt_(nullptr), - instruction_set_(kNone), + : instruction_set_(kNone), compiler_callbacks_(nullptr), is_zygote_(false), must_relocate_(false), @@ -147,9 +143,6 @@ Runtime::Runtime() implicit_null_checks_(false), implicit_so_checks_(false), implicit_suspend_checks_(false) { - for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { - callee_save_methods_[i] = nullptr; - } } Runtime::~Runtime() { @@ -716,7 +709,7 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) self->ThrowNewException(ThrowLocation(), "Ljava/lang/OutOfMemoryError;", "OutOfMemoryError thrown while trying to throw OutOfMemoryError; " "no stack available"); - pre_allocated_OutOfMemoryError_ = self->GetException(NULL); + pre_allocated_OutOfMemoryError_ = GcRoot<mirror::Throwable>(self->GetException(NULL)); self->ClearException(); // Look for a native bridge. @@ -931,8 +924,7 @@ void Runtime::DetachCurrentThread() { } mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryError() { - mirror::Throwable* oome = ReadBarrier::BarrierForRoot<mirror::Throwable, kWithReadBarrier>( - &pre_allocated_OutOfMemoryError_); + mirror::Throwable* oome = pre_allocated_OutOfMemoryError_.Read(); if (oome == NULL) { LOG(ERROR) << "Failed to return pre-allocated OOME"; } @@ -971,23 +963,21 @@ void Runtime::VisitConcurrentRoots(RootCallback* callback, void* arg, VisitRootF void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) { java_vm_->VisitRoots(callback, arg); - if (pre_allocated_OutOfMemoryError_ != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&pre_allocated_OutOfMemoryError_), arg, 0, - kRootVMInternal); - DCHECK(pre_allocated_OutOfMemoryError_ != nullptr); + if (!pre_allocated_OutOfMemoryError_.IsNull()) { + pre_allocated_OutOfMemoryError_.VisitRoot(callback, arg, 0, kRootVMInternal); + DCHECK(!pre_allocated_OutOfMemoryError_.IsNull()); } - callback(reinterpret_cast<mirror::Object**>(&resolution_method_), arg, 0, kRootVMInternal); - DCHECK(resolution_method_ != nullptr); + resolution_method_.VisitRoot(callback, arg, 0, kRootVMInternal); + DCHECK(!resolution_method_.IsNull()); if (HasImtConflictMethod()) { - callback(reinterpret_cast<mirror::Object**>(&imt_conflict_method_), arg, 0, kRootVMInternal); + imt_conflict_method_.VisitRoot(callback, arg, 0, kRootVMInternal); } if (HasDefaultImt()) { - callback(reinterpret_cast<mirror::Object**>(&default_imt_), arg, 0, kRootVMInternal); + default_imt_.VisitRoot(callback, arg, 0, kRootVMInternal); } for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { - if (callee_save_methods_[i] != nullptr) { - callback(reinterpret_cast<mirror::Object**>(&callee_save_methods_[i]), arg, 0, - kRootVMInternal); + if (!callee_save_methods_[i].IsNull()) { + callee_save_methods_[i].VisitRoot(callback, arg, 0, kRootVMInternal); } } { @@ -1125,7 +1115,7 @@ void Runtime::SetInstructionSet(InstructionSet instruction_set) { void Runtime::SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type) { DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType)); - callee_save_methods_[type] = method; + callee_save_methods_[type] = GcRoot<mirror::ArtMethod>(method); } const std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(jobject class_loader) { diff --git a/runtime/runtime.h b/runtime/runtime.h index c8e462e699..a85c2e4eda 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -27,6 +27,7 @@ #include <vector> #include "compiler_callbacks.h" +#include "gc_root.h" #include "instrumentation.h" #include "instruction_set.h" #include "jobject_comparator.h" @@ -282,11 +283,11 @@ class Runtime { mirror::ArtMethod* GetResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool HasResolutionMethod() const { - return resolution_method_ != nullptr; + return !resolution_method_.IsNull(); } void SetResolutionMethod(mirror::ArtMethod* method) { - resolution_method_ = method; + resolution_method_ = GcRoot<mirror::ArtMethod>(method); } mirror::ArtMethod* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -295,11 +296,11 @@ class Runtime { mirror::ArtMethod* GetImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool HasImtConflictMethod() const { - return imt_conflict_method_ != nullptr; + return !imt_conflict_method_.IsNull(); } void SetImtConflictMethod(mirror::ArtMethod* method) { - imt_conflict_method_ = method; + imt_conflict_method_ = GcRoot<mirror::ArtMethod>(method); } mirror::ArtMethod* CreateImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -309,11 +310,11 @@ class Runtime { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool HasDefaultImt() const { - return default_imt_ != nullptr; + return !default_imt_.IsNull(); } void SetDefaultImt(mirror::ObjectArray<mirror::ArtMethod>* imt) { - default_imt_ = imt; + default_imt_ = GcRoot<mirror::ObjectArray<mirror::ArtMethod>>(imt); } mirror::ObjectArray<mirror::ArtMethod>* CreateDefaultImt(ClassLinker* cl) @@ -328,7 +329,7 @@ class Runtime { }; bool HasCalleeSaveMethod(CalleeSaveType type) const { - return callee_save_methods_[type] != NULL; + return !callee_save_methods_[type].IsNull(); } mirror::ArtMethod* GetCalleeSaveMethod(CalleeSaveType type) @@ -488,11 +489,11 @@ class Runtime { static constexpr int kProfileForground = 0; static constexpr int kProfileBackgrouud = 1; - mirror::ArtMethod* callee_save_methods_[kLastCalleeSaveType]; - mirror::Throwable* pre_allocated_OutOfMemoryError_; - mirror::ArtMethod* resolution_method_; - mirror::ArtMethod* imt_conflict_method_; - mirror::ObjectArray<mirror::ArtMethod>* default_imt_; + GcRoot<mirror::ArtMethod> callee_save_methods_[kLastCalleeSaveType]; + GcRoot<mirror::Throwable> pre_allocated_OutOfMemoryError_; + GcRoot<mirror::ArtMethod> resolution_method_; + GcRoot<mirror::ArtMethod> imt_conflict_method_; + GcRoot<mirror::ObjectArray<mirror::ArtMethod>> default_imt_; InstructionSet instruction_set_; QuickMethodFrameInfo callee_save_method_frame_infos_[kLastCalleeSaveType]; diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h index d69162334d..23aca45002 100644 --- a/runtime/scoped_thread_state_change.h +++ b/runtime/scoped_thread_state_change.h @@ -19,6 +19,7 @@ #include "base/casts.h" #include "jni_internal-inl.h" +#include "read_barrier.h" #include "thread-inl.h" #include "verify_object.h" |