Faster implementation of Heap::RecordWrites.
authorantonm@chromium.org <antonm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 11 Jun 2010 17:03:19 +0000 (17:03 +0000)
committerantonm@chromium.org <antonm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 11 Jun 2010 17:03:19 +0000 (17:03 +0000)
Naive algorithm for to update RSets for a span is rather inefficient
as it performs many unnecessary operations (retrieving a mask, updating
it with the same bit as many pointers go into a single region).

Review URL: http://codereview.chromium.org/2727009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4849 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/heap-inl.h
src/spaces-inl.h
src/spaces.h

index cc558b8..5cb24ee 100644 (file)
@@ -196,12 +196,9 @@ void Heap::RecordWrite(Address address, int offset) {
 void Heap::RecordWrites(Address address, int start, int len) {
   if (new_space_.Contains(address)) return;
   ASSERT(!new_space_.FromSpaceContains(address));
-  for (int offset = start;
-       offset < start + len * kPointerSize;
-       offset += kPointerSize) {
-    SLOW_ASSERT(Contains(address + offset));
-    Page::FromAddress(address)->MarkRegionDirty(address + offset);
-  }
+  Page* page = Page::FromAddress(address);
+  page->SetRegionMarks(page->GetRegionMarks() |
+      page->GetRegionMaskForSpan(address + start, len * kPointerSize));
 }
 
 
index 862d5be..d49c207 100644 (file)
@@ -152,6 +152,33 @@ uint32_t Page::GetRegionMaskForAddress(Address addr) {
 }
 
 
+uint32_t Page::GetRegionMaskForSpan(Address start, int length_in_bytes) {
+  uint32_t result = 0;
+  if (length_in_bytes >= kPageSize) {
+    result = kAllRegionsDirtyMarks;
+  } else if (length_in_bytes > 0) {
+    int start_region = GetRegionNumberForAddress(start);
+    int end_region =
+        GetRegionNumberForAddress(start + length_in_bytes - kPointerSize);
+    uint32_t start_mask = (~0) << start_region;
+    uint32_t end_mask = ~((~1) << end_region);
+    result = start_mask & end_mask;
+    // if end_region < start_region, the mask is ored.
+    if (result == 0) result = start_mask | end_mask;
+  }
+#ifdef DEBUG
+  if (FLAG_enable_slow_asserts) {
+    uint32_t expected = 0;
+    for (Address a = start; a < start + length_in_bytes; a += kPointerSize) {
+      expected |= GetRegionMaskForAddress(a);
+    }
+    ASSERT(expected == result);
+  }
+#endif
+  return result;
+}
+
+
 void Page::MarkRegionDirty(Address address) {
   SetRegionMarks(GetRegionMarks() | GetRegionMaskForAddress(address));
 }
index 32a3e6c..051ce37 100644 (file)
@@ -220,6 +220,7 @@ class Page {
   inline void SetRegionMarks(uint32_t dirty);
 
   inline uint32_t GetRegionMaskForAddress(Address addr);
+  inline uint32_t GetRegionMaskForSpan(Address start, int length_in_bytes);
   inline int GetRegionNumberForAddress(Address addr);
 
   inline void MarkRegionDirty(Address addr);