summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHiroshi Yamauchi <yamauchi@google.com>2014-07-22 18:08:23 -0700
committerHiroshi Yamauchi <yamauchi@google.com>2014-07-29 13:30:46 -0700
commit94f7b49578b6aaa80de8ffed230648d601393905 (patch)
treecfc69e453faefee38178ceb85378e1f0f1e17812
parent8df73882c60451e7f789bf9b1f3db2d7dc228640 (diff)
downloadart-94f7b49578b6aaa80de8ffed230648d601393905.tar.gz
art-94f7b49578b6aaa80de8ffed230648d601393905.tar.bz2
art-94f7b49578b6aaa80de8ffed230648d601393905.zip
Add GcRoot to clean up and enforce read barriers.
Introduce a value-type wrapper around Object* for GC roots so that 1) we won't have to directly add the read barrier code in many places and 2) we can avoid accidentally bypassing/missing read barriers on GC roots (the GcRoot interface ensures that the read barrier is executed on a read). The jdwp test passed. Bug: 12687968 Change-Id: Ib167c7c325b3c7e3900133578815f04d219972a1
-rw-r--r--runtime/class_linker-inl.h14
-rw-r--r--runtime/class_linker.cc101
-rw-r--r--runtime/class_linker.h24
-rw-r--r--runtime/common_runtime_test.cc1
-rw-r--r--runtime/gc_root-inl.h33
-rw-r--r--runtime/gc_root.h58
-rw-r--r--runtime/indirect_reference_table-inl.h8
-rw-r--r--runtime/indirect_reference_table.cc34
-rw-r--r--runtime/indirect_reference_table.h23
-rw-r--r--runtime/instrumentation.cc15
-rw-r--r--runtime/instrumentation.h4
-rw-r--r--runtime/intern_table.cc52
-rw-r--r--runtime/intern_table.h11
-rw-r--r--runtime/jni_internal.cc12
-rw-r--r--runtime/jni_internal.h6
-rw-r--r--runtime/mirror/array-inl.h4
-rw-r--r--runtime/mirror/array.cc2
-rw-r--r--runtime/mirror/array.h17
-rw-r--r--runtime/mirror/art_field.cc15
-rw-r--r--runtime/mirror/art_field.h10
-rw-r--r--runtime/mirror/art_method-inl.h5
-rw-r--r--runtime/mirror/art_method.cc15
-rw-r--r--runtime/mirror/art_method.h3
-rw-r--r--runtime/mirror/class.cc21
-rw-r--r--runtime/mirror/class.h10
-rw-r--r--runtime/mirror/reference.cc15
-rw-r--r--runtime/mirror/reference.h10
-rw-r--r--runtime/mirror/stack_trace_element.cc15
-rw-r--r--runtime/mirror/stack_trace_element.h9
-rw-r--r--runtime/mirror/string.cc14
-rw-r--r--runtime/mirror/string.h9
-rw-r--r--runtime/mirror/throwable.cc14
-rw-r--r--runtime/mirror/throwable.h9
-rw-r--r--runtime/monitor.cc8
-rw-r--r--runtime/monitor.h7
-rw-r--r--runtime/reference_table.cc35
-rw-r--r--runtime/reference_table.h3
-rw-r--r--runtime/runtime-inl.h13
-rw-r--r--runtime/runtime.cc36
-rw-r--r--runtime/runtime.h25
-rw-r--r--runtime/scoped_thread_state_change.h1
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"