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_;