Add missing filter cards to zygote mod union table

Without filtering the cards, every object in the zygote is grayed
during the GC. This was deleted in a PS of previous CL.

GrayAllDirtyImmuneObjects goes from 1.974ms to 376.464us for CC on
N9 maps. This happens during the pause. This CL also fixes regression
in zygote PSS.

Bug: 29516968
Bug: 12687968

Change-Id: I42014e78b1de3ce9b2eefa3bd32f0d24e2ff71c6
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 32425d8..70a907f 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -90,10 +90,12 @@
   if (kIsDebugBuild) {
     Thread* self = Thread::Current();
     if (!Locks::mutator_lock_->IsSharedHeld(self)) {
-      ScopedObjectAccess soa(self);
-      CHECK(IsRuntimeMethod() ||
-            GetDeclaringClass<kReadBarrierOption>()->IsIdxLoaded() ||
-            GetDeclaringClass<kReadBarrierOption>()->IsErroneous());
+      if (self->IsThreadSuspensionAllowable()) {
+        ScopedObjectAccess soa(self);
+        CHECK(IsRuntimeMethod() ||
+              GetDeclaringClass<kReadBarrierOption>()->IsIdxLoaded() ||
+              GetDeclaringClass<kReadBarrierOption>()->IsErroneous());
+      }
     } else {
       // We cannot use SOA in this case. We might be holding the lock, but may not be in the
       // runnable state (e.g., during GC).
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 6f4767e..74e6c3c 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2546,6 +2546,9 @@
   // Set all the cards in the mod-union table since we don't know which objects contain references
   // to large objects.
   mod_union_table->SetCards();
+  // Filter out cards that do not to be dirty. This is mostly for CC collector so that it does
+  // not gray the objects on all the cards in the zygote space.
+  mod_union_table->FilterCards();
   AddModUnionTable(mod_union_table);
   large_object_space_->SetAllLargeObjectsAsZygoteObjects(self);
   if (collector::SemiSpace::kUseRememberedSet) {
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index 3fd66a7..3aa1fc2 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -93,6 +93,18 @@
   return static_cast<ThreadState>(old_state_and_flags.as_struct.state);
 }
 
+inline bool Thread::IsThreadSuspensionAllowable() const {
+  if (tls32_.no_thread_suspension != 0) {
+    return false;
+  }
+  for (int i = kLockLevelCount - 1; i >= 0; --i) {
+    if (i != kMutatorLock && GetHeldMutex(static_cast<LockLevel>(i)) != nullptr) {
+      return false;
+    }
+  }
+  return true;
+}
+
 inline void Thread::AssertThreadSuspensionIsAllowable(bool check_locks) const {
   if (kIsDebugBuild) {
     if (gAborting == 0) {
diff --git a/runtime/thread.h b/runtime/thread.h
index a3a4005..9a4eb97 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -287,6 +287,9 @@
 
   void AssertThreadSuspensionIsAllowable(bool check_locks = true) const;
 
+  // Return true if thread suspension is allowable.
+  bool IsThreadSuspensionAllowable() const;
+
   bool IsDaemon() const {
     return tls32_.daemon;
   }