Rewrite bits of RegionSpace::ClearFromSpace.

To make it clearer what the loop is for.

Test: test.py
Change-Id: Iae5d8351fd294a4f43dd74dc714d644c9d8f0c7f
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index b8f1e8f..fe3c1c0 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -290,6 +290,7 @@
       clear_region(r);
     } else if (r->IsInUnevacFromSpace()) {
       if (r->LiveBytes() == 0) {
+        DCHECK(!r->IsLargeTail());
         // Special case for 0 live bytes, this means all of the objects in the region are dead and
         // we can clear it. This is important for large objects since we must not visit dead ones in
         // RegionSpace::Walk because they may contain dangling references to invalid objects.
@@ -312,28 +313,29 @@
             reinterpret_cast<mirror::Object*>(r->Begin() + free_regions * kRegionSize));
         continue;
       }
-      size_t full_count = 0;
-      while (r->IsInUnevacFromSpace()) {
-        Region* const cur = &regions_[i + full_count];
-        if (i + full_count >= num_regions_ ||
-            cur->LiveBytes() != static_cast<size_t>(cur->Top() - cur->Begin())) {
-          break;
-        }
-        DCHECK(cur->IsInUnevacFromSpace());
-        if (full_count != 0) {
-          cur->SetUnevacFromSpaceAsToSpace();
-        }
-        ++full_count;
-      }
-      // Note that r is the full_count == 0 iteration since it is not handled by the loop.
       r->SetUnevacFromSpaceAsToSpace();
-      if (full_count >= 1) {
+      if (r->AllAllocatedBytesAreLive()) {
+        // Try to optimize the number of ClearRange calls by checking whether the next regions
+        // can also be cleared.
+        size_t regions_to_clear_bitmap = 1;
+        while (i + regions_to_clear_bitmap < num_regions_) {
+          Region* const cur = &regions_[i + regions_to_clear_bitmap];
+          if (!cur->AllAllocatedBytesAreLive()) {
+            DCHECK(!cur->IsLargeTail());
+            break;
+          }
+          CHECK(cur->IsInUnevacFromSpace());
+          cur->SetUnevacFromSpaceAsToSpace();
+          ++regions_to_clear_bitmap;
+        }
+
         GetLiveBitmap()->ClearRange(
             reinterpret_cast<mirror::Object*>(r->Begin()),
-            reinterpret_cast<mirror::Object*>(r->Begin() + full_count * kRegionSize));
-        // Skip over extra regions we cleared.
+            reinterpret_cast<mirror::Object*>(r->Begin() + regions_to_clear_bitmap * kRegionSize));
+        // Skip over extra regions we cleared the bitmaps: we don't need to clear them, as they
+        // are unevac region sthat are live.
         // Subtract one for the for loop.
-        i += full_count - 1;
+        i += regions_to_clear_bitmap - 1;
       }
     }
     // Note r != last_checked_region if r->IsInUnevacFromSpace() was true above.
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index 7b16ffe..6412158 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -393,6 +393,10 @@
       DCHECK_LE(live_bytes_, BytesAllocated());
     }
 
+    bool AllAllocatedBytesAreLive() const {
+      return LiveBytes() == static_cast<size_t>(Top() - Begin());
+    }
+
     size_t LiveBytes() const {
       return live_bytes_;
     }