Sweep the monitor list.
Change-Id: I343261206f8bbabd245b404dd95d532255e5d870
diff --git a/src/heap.h b/src/heap.h
index c25803f..aa9db6e 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -40,6 +40,7 @@
static const size_t kMaximumSize = 16 * MB;
typedef void (RootVisitor)(const Object* root, void* arg);
+ typedef bool (IsMarkedTester)(const Object* object, void* arg);
// Create a heap with the requested sizes. The possible empty
// image_file_names names specify Spaces to load based on
diff --git a/src/intern_table.cc b/src/intern_table.cc
index aa27ace..53208fd 100644
--- a/src/intern_table.cc
+++ b/src/intern_table.cc
@@ -119,11 +119,12 @@
return found == s;
}
-void InternTable::RemoveWeakIf(const Predicate& predicate) {
+void InternTable::SweepInternTableWeaks(Heap::IsMarkedTester is_marked, void* arg) {
MutexLock mu(intern_table_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
for (It it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) {
- if (predicate(it->second)) {
+ Object* object = it->second;
+ if (!is_marked(object, arg)) {
weak_interns_.erase(it++);
} else {
++it;
diff --git a/src/intern_table.h b/src/intern_table.h
index c814a1b..d573538 100644
--- a/src/intern_table.h
+++ b/src/intern_table.h
@@ -41,14 +41,7 @@
// Used when reinitializing InternTable from an image.
void RegisterStrong(String* s);
- // Removes all weak interns for which the predicate functor 'p' returns true.
- // (We use an explicit Predicate type rather than a template to keep implementation
- // out of the header file.)
- struct Predicate {
- virtual ~Predicate() {}
- virtual bool operator()(const String*) const = 0;
- };
- void RemoveWeakIf(const Predicate& p);
+ void SweepInternTableWeaks(Heap::IsMarkedTester is_marked, void* arg);
bool ContainsWeak(String* s);
diff --git a/src/intern_table_test.cc b/src/intern_table_test.cc
index 3f9fab0..d9a6a45 100644
--- a/src/intern_table_test.cc
+++ b/src/intern_table_test.cc
@@ -36,9 +36,9 @@
EXPECT_EQ(2U, t.Size());
}
-class TestPredicate : public InternTable::Predicate {
+class TestPredicate {
public:
- bool operator()(const String* s) const {
+ bool IsMarked(const Object* s) const {
bool erased = false;
typedef std::vector<const String*>::iterator It; // TODO: C++0x auto
for (It it = expected_.begin(), end = expected_.end(); it != end; ++it) {
@@ -49,7 +49,7 @@
}
}
EXPECT_TRUE(erased);
- return true;
+ return false;
}
void Expect(const String* s) {
@@ -64,7 +64,11 @@
mutable std::vector<const String*> expected_;
};
-TEST_F(InternTableTest, RemoveWeakIf) {
+bool IsMarked(const Object* object, void* arg) {
+ return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object);
+}
+
+TEST_F(InternTableTest, SweepInternTableWeaks) {
InternTable t;
t.InternStrong(3, "foo");
t.InternStrong(3, "bar");
@@ -77,7 +81,7 @@
TestPredicate p;
p.Expect(s0);
p.Expect(s1);
- t.RemoveWeakIf(p);
+ t.SweepInternTableWeaks(IsMarked, &p);
EXPECT_EQ(2U, t.Size());
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index 05f229d..79597ec 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -13,6 +13,7 @@
#include "logging.h"
#include "macros.h"
#include "mark_stack.h"
+#include "monitor.h"
#include "object.h"
#include "runtime.h"
#include "space.h"
@@ -125,24 +126,9 @@
}
}
-struct InternTableEntryIsUnmarked : public InternTable::Predicate {
- InternTableEntryIsUnmarked(MarkSweep* ms) : ms_(ms) { }
-
- bool operator()(const String* s) const {
- return !ms_->IsMarked(s);
- }
-
- MarkSweep* ms_;
-};
-
-void MarkSweep::SweepMonitorList() {
- UNIMPLEMENTED(WARNING);
- //dvmSweepMonitorList(&gDvm.monitorList, isUnmarkedObject);
-}
-
void MarkSweep::SweepSystemWeaks() {
- Runtime::Current()->GetInternTable()->RemoveWeakIf(InternTableEntryIsUnmarked(this));
- SweepMonitorList();
+ Runtime::Current()->GetInternTable()->SweepInternTableWeaks(IsMarked, this);
+ Runtime::Current()->GetMonitorList()->SweepMonitorList(IsMarked, this);
SweepJniWeakGlobals();
}
diff --git a/src/mark_sweep.h b/src/mark_sweep.h
index cf099ad..bcb4df0 100644
--- a/src/mark_sweep.h
+++ b/src/mark_sweep.h
@@ -59,6 +59,10 @@
return mark_bitmap_->Test(object);
}
+ static bool IsMarked(const Object* object, void* arg) {
+ return reinterpret_cast<MarkSweep*>(arg)->IsMarked(object);
+ }
+
static void MarkObjectVisitor(const Object* root, void* arg);
// Marks an object.
@@ -112,7 +116,6 @@
Object** phantom_references);
void SweepSystemWeaks();
- void SweepMonitorList();
void SweepJniWeakGlobals();
MarkStack* mark_stack_;
diff --git a/src/monitor.cc b/src/monitor.cc
index 9a0233f..bc577a4 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -26,6 +26,7 @@
#include "mutex.h"
#include "object.h"
+#include "stl_util.h"
#include "thread.h"
#include "thread_list.h"
@@ -94,6 +95,10 @@
bool Monitor::is_verbose_ = false;
+bool Monitor::IsVerbose() {
+ return is_verbose_;
+}
+
void Monitor::SetVerbose(bool is_verbose) {
is_verbose_ = is_verbose;
}
@@ -104,7 +109,6 @@
obj_(obj),
wait_set_(NULL),
lock_("a monitor lock"),
- next_(NULL),
owner_filename_(NULL),
owner_line_number_(0) {
}
@@ -174,48 +178,8 @@
}
}
-// Global list of all monitors. Used for cleanup.
-static Monitor* gMonitorList = NULL;
-
-void Monitor::FreeMonitorList() {
- Monitor* m = gMonitorList;
- while (m != NULL) {
- Monitor* next = m->next_;
- delete m;
- m = next;
- }
-}
-
-/*
- * Frees monitor objects belonging to unmarked objects.
- */
-static void SweepMonitorList(Monitor** mon, bool (isUnmarkedObject)(void*)) {
- UNIMPLEMENTED(FATAL);
-#if 0
- Monitor handle;
- Monitor *curr;
-
- DCHECK(mon != NULL);
- DCHECK(isUnmarkedObject != NULL);
- Monitor* prev = &handle;
- prev->next = curr = *mon;
- while (curr != NULL) {
- Object* obj = curr->obj;
- if ((*isUnmarkedObject)(obj) != 0) {
- prev->next = curr->next;
- delete curr;
- curr = prev->next;
- } else {
- prev = curr;
- curr = curr->next;
- }
- }
- *mon = handle.next;
-#endif
-}
-
-void Monitor::SweepMonitorList(bool (isUnmarkedObject)(void*)) {
- ::art::SweepMonitorList(&gMonitorList, isUnmarkedObject);
+Object* Monitor::GetObject() {
+ return obj_;
}
/*
@@ -648,10 +612,7 @@
if (is_verbose_) {
LOG(INFO) << "monitor: created monitor " << m << " for object " << obj;
}
- // Replace the head of the list with the new monitor.
- do {
- m->next_ = gMonitorList;
- } while (android_atomic_release_cas((int32_t)m->next_, (int32_t)m, (int32_t*)(void*)&gMonitorList) != 0);
+ Runtime::Current()->GetMonitorList()->Add(m);
m->Lock(self);
// Propagate the lock state.
uint32_t thin = *obj->GetRawLockWordAddress();
@@ -945,4 +906,35 @@
os << "\n";
}
+MonitorList::MonitorList() : lock_("MonitorList lock") {
+}
+
+MonitorList::~MonitorList() {
+ MutexLock mu(lock_);
+ STLDeleteElements(&list_);
+}
+
+void MonitorList::Add(Monitor* m) {
+ MutexLock mu(lock_);
+ list_.push_front(m);
+}
+
+void MonitorList::SweepMonitorList(Heap::IsMarkedTester is_marked, void* arg) {
+ MutexLock mu(lock_);
+ typedef std::list<Monitor*>::iterator It; // TODO: C++0x auto
+ It it = list_.begin();
+ while (it != list_.end()) {
+ Monitor* m = *it;
+ if (!is_marked(m->GetObject(), arg)) {
+ if (Monitor::IsVerbose()) {
+ LOG(INFO) << "freeing monitor " << m << " belonging to unmarked object " << m->GetObject();
+ }
+ delete m;
+ it = list_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
} // namespace art
diff --git a/src/monitor.h b/src/monitor.h
index 9ea407e..1316532 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -21,7 +21,9 @@
#include <stdint.h>
#include <iosfwd>
+#include <list>
+#include "heap.h"
#include "mutex.h"
namespace art {
@@ -60,6 +62,7 @@
public:
~Monitor();
+ static bool IsVerbose();
static void SetVerbose(bool is_verbose);
static uint32_t GetLockOwner(uint32_t raw_lock_word);
@@ -71,12 +74,10 @@
static void NotifyAll(Thread* self, Object* obj);
static void Wait(Thread* self, Object* obj, int64_t ms, int32_t ns, bool interruptShouldThrow);
- static void SweepMonitorList(bool (isUnmarkedObject)(void*));
-
- static void FreeMonitorList();
-
static void DescribeWait(std::ostream& os, const Thread* thread);
+ Object* GetObject();
+
private:
Monitor(Object* obj);
@@ -109,8 +110,6 @@
Mutex lock_;
- Monitor* next_;
-
/*
* Who last acquired this monitor, when lock sampling is enabled.
* Even when enabled, ownerFileName may be NULL.
@@ -119,6 +118,23 @@
uint32_t owner_line_number_;
friend class Object;
+ DISALLOW_COPY_AND_ASSIGN(Monitor);
+};
+
+class MonitorList {
+ public:
+ MonitorList();
+ ~MonitorList();
+
+ void Add(Monitor* m);
+
+ void SweepMonitorList(Heap::IsMarkedTester is_marked, void* arg);
+
+ private:
+ Mutex lock_;
+ std::list<Monitor*> list_;
+
+ DISALLOW_COPY_AND_ASSIGN(MonitorList);
};
/*
diff --git a/src/runtime.cc b/src/runtime.cc
index e0c9d47..a707c4d 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -34,6 +34,7 @@
: verbose_startup_(false),
is_zygote_(false),
default_stack_size_(Thread::kDefaultStackSize),
+ monitor_list_(NULL),
thread_list_(NULL),
intern_table_(NULL),
class_linker_(NULL),
@@ -61,6 +62,7 @@
// Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
delete thread_list_;
+ delete monitor_list_;
delete class_linker_;
Heap::Destroy();
@@ -426,6 +428,7 @@
default_stack_size_ = options->stack_size_;
+ monitor_list_ = new MonitorList;
thread_list_ = new ThreadList(options->IsVerbose("thread"));
intern_table_ = new InternTable;
diff --git a/src/runtime.h b/src/runtime.h
index 462bb81..84302a9 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -31,6 +31,7 @@
class InternTable;
class JavaVMExt;
class Method;
+class MonitorList;
class SignalCatcher;
class String;
class ThreadList;
@@ -140,6 +141,10 @@
return properties_;
}
+ MonitorList* GetMonitorList() const {
+ return monitor_list_;
+ }
+
ThreadList* GetThreadList() const {
return thread_list_;
}
@@ -230,6 +235,8 @@
// The default stack size for managed threads created by the runtime.
size_t default_stack_size_;
+ MonitorList* monitor_list_;
+
ThreadList* thread_list_;
InternTable* intern_table_;