diff options
author | Mathieu Chartier <mathieuc@google.com> | 2013-09-18 00:33:00 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-09-18 00:33:01 +0000 |
commit | 8c7ec8cd8e39809ed31cb62bc3b068430042bd76 (patch) | |
tree | 0ef55b9099fab8a4216e06ce67655d38f7a43940 | |
parent | b307052d619ec757478951fc026e6230c92e3b36 (diff) | |
parent | 6aa3df965395566ed6a4fec4af37c2b7577992e9 (diff) | |
download | art-8c7ec8cd8e39809ed31cb62bc3b068430042bd76.zip art-8c7ec8cd8e39809ed31cb62bc3b068430042bd76.tar.gz art-8c7ec8cd8e39809ed31cb62bc3b068430042bd76.tar.bz2 |
Merge "Refactor system weak sweeping, add support for modification." into dalvik-dev
-rw-r--r-- | runtime/gc/collector/mark_sweep.cc | 54 | ||||
-rw-r--r-- | runtime/gc/collector/mark_sweep.h | 9 | ||||
-rw-r--r-- | runtime/intern_table.cc | 8 | ||||
-rw-r--r-- | runtime/intern_table.h | 3 | ||||
-rw-r--r-- | runtime/intern_table_test.cc | 9 | ||||
-rw-r--r-- | runtime/jni_internal.cc | 12 | ||||
-rw-r--r-- | runtime/jni_internal.h | 2 | ||||
-rw-r--r-- | runtime/monitor.cc | 14 | ||||
-rw-r--r-- | runtime/monitor.h | 6 | ||||
-rw-r--r-- | runtime/runtime.cc | 6 | ||||
-rw-r--r-- | runtime/runtime.h | 4 |
11 files changed, 71 insertions, 56 deletions
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index f724cdb..5d9db83 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -944,10 +944,12 @@ void MarkSweep::RecursiveMark() { ProcessMarkStack(false); } -bool MarkSweep::IsMarkedCallback(const Object* object, void* arg) { - return - reinterpret_cast<MarkSweep*>(arg)->IsMarked(object) || - !reinterpret_cast<MarkSweep*>(arg)->GetHeap()->GetLiveBitmap()->Test(object); +mirror::Object* MarkSweep::SystemWeakIsMarkedCallback(Object* object, void* arg) { + if (reinterpret_cast<MarkSweep*>(arg)->IsMarked(object) || + !reinterpret_cast<MarkSweep*>(arg)->GetHeap()->GetLiveBitmap()->Test(object)) { + return object; + } + return nullptr; } void MarkSweep::RecursiveMarkDirtyObjects(bool paused, byte minimum_age) { @@ -961,29 +963,22 @@ void MarkSweep::ReMarkRoots() { timings_.EndSplit(); } -void MarkSweep::SweepJniWeakGlobals(IsMarkedTester is_marked, void* arg) { - JavaVMExt* vm = Runtime::Current()->GetJavaVM(); - WriterMutexLock mu(Thread::Current(), vm->weak_globals_lock); - for (Object** entry : vm->weak_globals) { - if (!is_marked(*entry, arg)) { - *entry = kClearedJniWeakGlobal; - } - } -} - struct ArrayMarkedCheck { accounting::ObjectStack* live_stack; MarkSweep* mark_sweep; }; // Either marked or not live. -bool MarkSweep::IsMarkedArrayCallback(const Object* object, void* arg) { +mirror::Object* MarkSweep::SystemWeakIsMarkedArrayCallback(Object* object, void* arg) { ArrayMarkedCheck* array_check = reinterpret_cast<ArrayMarkedCheck*>(arg); if (array_check->mark_sweep->IsMarked(object)) { - return true; + return object; } accounting::ObjectStack* live_stack = array_check->live_stack; - return std::find(live_stack->Begin(), live_stack->End(), object) == live_stack->End(); + if (std::find(live_stack->Begin(), live_stack->End(), object) == live_stack->End()) { + return object; + } + return nullptr; } void MarkSweep::SweepSystemWeaksArray(accounting::ObjectStack* allocations) { @@ -993,14 +988,11 @@ void MarkSweep::SweepSystemWeaksArray(accounting::ObjectStack* allocations) { // !IsMarked && IsLive // So compute !(!IsMarked && IsLive) which is equal to (IsMarked || !IsLive). // Or for swapped (IsLive || !IsMarked). - timings_.StartSplit("SweepSystemWeaksArray"); ArrayMarkedCheck visitor; visitor.live_stack = allocations; visitor.mark_sweep = this; - runtime->GetInternTable()->SweepInternTableWeaks(IsMarkedArrayCallback, &visitor); - runtime->GetMonitorList()->SweepMonitorList(IsMarkedArrayCallback, &visitor); - SweepJniWeakGlobals(IsMarkedArrayCallback, &visitor); + runtime->SweepSystemWeaks(SystemWeakIsMarkedArrayCallback, &visitor); timings_.EndSplit(); } @@ -1012,16 +1004,14 @@ void MarkSweep::SweepSystemWeaks() { // So compute !(!IsMarked && IsLive) which is equal to (IsMarked || !IsLive). // Or for swapped (IsLive || !IsMarked). timings_.StartSplit("SweepSystemWeaks"); - runtime->GetInternTable()->SweepInternTableWeaks(IsMarkedCallback, this); - runtime->GetMonitorList()->SweepMonitorList(IsMarkedCallback, this); - SweepJniWeakGlobals(IsMarkedCallback, this); + runtime->SweepSystemWeaks(SystemWeakIsMarkedCallback, this); timings_.EndSplit(); } -bool MarkSweep::VerifyIsLiveCallback(const Object* obj, void* arg) { +mirror::Object* MarkSweep::VerifySystemWeakIsLiveCallback(Object* obj, void* arg) { reinterpret_cast<MarkSweep*>(arg)->VerifyIsLive(obj); // We don't actually want to sweep the object, so lets return "marked" - return true; + return obj; } void MarkSweep::VerifyIsLive(const Object* obj) { @@ -1040,16 +1030,8 @@ void MarkSweep::VerifyIsLive(const Object* obj) { } void MarkSweep::VerifySystemWeaks() { - Runtime* runtime = Runtime::Current(); - // Verify system weaks, uses a special IsMarked callback which always returns true. - runtime->GetInternTable()->SweepInternTableWeaks(VerifyIsLiveCallback, this); - runtime->GetMonitorList()->SweepMonitorList(VerifyIsLiveCallback, this); - - JavaVMExt* vm = runtime->GetJavaVM(); - ReaderMutexLock mu(Thread::Current(), vm->weak_globals_lock); - for (Object** entry : vm->weak_globals) { - VerifyIsLive(*entry); - } + // Verify system weaks, uses a special object visitor which returns the input object. + Runtime::Current()->SweepSystemWeaks(VerifySystemWeakIsLiveCallback, this); } struct SweepCallbackContext { diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h index 8b6ac15..a857dab 100644 --- a/runtime/gc/collector/mark_sweep.h +++ b/runtime/gc/collector/mark_sweep.h @@ -208,7 +208,7 @@ class MarkSweep : public GarbageCollector { void SweepSystemWeaksArray(accounting::ObjectStack* allocations) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - static bool VerifyIsLiveCallback(const mirror::Object* obj, void* arg) + static mirror::Object* VerifySystemWeakIsLiveCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); void VerifySystemWeaks() @@ -246,10 +246,10 @@ class MarkSweep : public GarbageCollector { // Returns true if the object has its bit set in the mark bitmap. bool IsMarked(const mirror::Object* object) const; - static bool IsMarkedCallback(const mirror::Object* object, void* arg) + static mirror::Object* SystemWeakIsMarkedCallback(mirror::Object* object, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - static bool IsMarkedArrayCallback(const mirror::Object* object, void* arg) + static mirror::Object* SystemWeakIsMarkedArrayCallback(mirror::Object* object, void* arg) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); static void VerifyImageRootVisitor(mirror::Object* root, void* arg) @@ -390,9 +390,6 @@ class MarkSweep : public GarbageCollector { EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SweepJniWeakGlobals(IsMarkedTester is_marked, void* arg) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); - // Whether or not we count how many of each type of object were scanned. static const bool kCountScannedTypes = false; diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc index 472c92e..29d2ae9 100644 --- a/runtime/intern_table.cc +++ b/runtime/intern_table.cc @@ -197,14 +197,16 @@ bool InternTable::ContainsWeak(mirror::String* s) { return found == s; } -void InternTable::SweepInternTableWeaks(IsMarkedTester is_marked, void* arg) { +void InternTable::SweepInternTableWeaks(RootVisitor visitor, void* arg) { MutexLock mu(Thread::Current(), intern_table_lock_); - // TODO: std::remove_if + lambda. for (auto it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) { mirror::Object* object = it->second; - if (!is_marked(object, arg)) { + mirror::Object* new_object = visitor(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; } } diff --git a/runtime/intern_table.h b/runtime/intern_table.h index 07615dc..9806130 100644 --- a/runtime/intern_table.h +++ b/runtime/intern_table.h @@ -55,8 +55,7 @@ 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(IsMarkedTester is_marked, void* arg) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); + void SweepInternTableWeaks(RootVisitor visitor, void* arg); bool ContainsWeak(mirror::String* s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/intern_table_test.cc b/runtime/intern_table_test.cc index d79d2c4..aa2502d 100644 --- a/runtime/intern_table_test.cc +++ b/runtime/intern_table_test.cc @@ -81,8 +81,11 @@ class TestPredicate { mutable std::vector<const mirror::String*> expected_; }; -bool IsMarked(const mirror::Object* object, void* arg) { - return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object); +mirror::Object* IsMarkedSweepingVisitor(mirror::Object* object, void* arg) { + if (reinterpret_cast<TestPredicate*>(arg)->IsMarked(object)) { + return object; + } + return nullptr; } TEST_F(InternTableTest, SweepInternTableWeaks) { @@ -105,7 +108,7 @@ TEST_F(InternTableTest, SweepInternTableWeaks) { p.Expect(s1.get()); { ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_); - t.SweepInternTableWeaks(IsMarked, &p); + t.SweepInternTableWeaks(IsMarkedSweepingVisitor, &p); } EXPECT_EQ(2U, t.Size()); diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index b471599..7f0fde4 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -3217,6 +3217,18 @@ void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m) { return native_method; } +void JavaVMExt::SweepJniWeakGlobals(RootVisitor visitor, void* arg) { + WriterMutexLock mu(Thread::Current(), weak_globals_lock); + for (mirror::Object** entry : weak_globals) { + mirror::Object* obj = *entry; + mirror::Object* new_obj = visitor(obj, arg); + if (new_obj == nullptr) { + new_obj = kClearedJniWeakGlobal; + } + *entry = new_obj; + } +} + void JavaVMExt::VisitRoots(RootVisitor* visitor, void* arg) { Thread* self = Thread::Current(); { diff --git a/runtime/jni_internal.h b/runtime/jni_internal.h index bad3841..2fcebf0 100644 --- a/runtime/jni_internal.h +++ b/runtime/jni_internal.h @@ -89,6 +89,8 @@ struct JavaVMExt : public JavaVM { void SetCheckJniEnabled(bool enabled); + void SweepJniWeakGlobals(RootVisitor visitor, void* arg); + void VisitRoots(RootVisitor*, void*); Runtime* runtime; diff --git a/runtime/monitor.cc b/runtime/monitor.cc index 92e6541..570c2be 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -194,6 +194,10 @@ mirror::Object* Monitor::GetObject() { return obj_; } +void Monitor::SetObject(mirror::Object* object) { + obj_ = object; +} + void Monitor::Lock(Thread* self) { if (owner_ == self) { lock_count_++; @@ -1001,15 +1005,19 @@ void MonitorList::Add(Monitor* m) { list_.push_front(m); } -void MonitorList::SweepMonitorList(IsMarkedTester is_marked, void* arg) { +void MonitorList::SweepMonitorList(RootVisitor visitor, void* arg) { MutexLock mu(Thread::Current(), monitor_list_lock_); for (auto it = list_.begin(); it != list_.end(); ) { Monitor* m = *it; - if (!is_marked(m->GetObject(), arg)) { - VLOG(monitor) << "freeing monitor " << m << " belonging to unmarked object " << m->GetObject(); + mirror::Object* obj = m->GetObject(); + mirror::Object* new_obj = visitor(obj, arg); + if (new_obj == nullptr) { + VLOG(monitor) << "freeing monitor " << m << " belonging to unmarked object " + << m->GetObject(); delete m; it = list_.erase(it); } else { + m->SetObject(new_obj); ++it; } } diff --git a/runtime/monitor.h b/runtime/monitor.h index 6651768..4249316 100644 --- a/runtime/monitor.h +++ b/runtime/monitor.h @@ -103,6 +103,7 @@ class Monitor { static bool IsValidLockWord(int32_t lock_word); mirror::Object* GetObject(); + void SetObject(mirror::Object* object); private: explicit Monitor(Thread* owner, mirror::Object* obj) @@ -159,7 +160,7 @@ class Monitor { int lock_count_ GUARDED_BY(monitor_lock_); // What object are we part of (for debugging). - mirror::Object* const obj_; + mirror::Object* obj_; // Threads currently waiting on this monitor. Thread* wait_set_ GUARDED_BY(monitor_lock_); @@ -183,8 +184,7 @@ class MonitorList { void Add(Monitor* m); - void SweepMonitorList(IsMarkedTester is_marked, void* arg) - SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_); + void SweepMonitorList(RootVisitor visitor, void* arg); private: Mutex monitor_list_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 02ed59f..fe33185 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -319,6 +319,12 @@ size_t ParseIntegerOrDie(const std::string& s) { return result; } +void Runtime::SweepSystemWeaks(RootVisitor* visitor, void* arg) { + GetInternTable()->SweepInternTableWeaks(visitor, arg); + GetMonitorList()->SweepMonitorList(visitor, arg); + GetJavaVM()->SweepJniWeakGlobals(visitor, arg); +} + Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) { UniquePtr<ParsedOptions> parsed(new ParsedOptions()); const char* boot_class_path_string = getenv("BOOTCLASSPATH"); diff --git a/runtime/runtime.h b/runtime/runtime.h index 21161a0..5acd5d7 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -317,6 +317,10 @@ class Runtime { void VisitNonConcurrentRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Sweep system weaks, the system weak is deleted if the visitor return nullptr. Otherwise, the + // system weak is updated to be the visitor's returned value. + void SweepSystemWeaks(RootVisitor* visitor, void* arg); + // Returns a special method that calls into a trampoline for runtime method resolution mirror::ArtMethod* GetResolutionMethod() const { CHECK(HasResolutionMethod()); |