Reviewers: Vyacheslav Egorov,

Message:
Slava,

may you have a look?

I'd esp. appreciate careful check if mask calculating algorithm is correct.

Description:
Faster implementation of Heap::RecordWrites.

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).

Please review this at http://codereview.chromium.org/2727009/show

Affected files:
  M src/heap-inl.h
  M src/spaces-inl.h
  M src/spaces.h


Index: src/heap-inl.h
diff --git a/src/heap-inl.h b/src/heap-inl.h
index cc558b8248bb767b47ecb0a09081ec0050861b49..5cb24eec2f05c70b742dffea80bceea349830009 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -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: src/spaces-inl.h
diff --git a/src/spaces-inl.h b/src/spaces-inl.h
index 862d5bee5a7da482728cd62056b17ca28848f0b0..c4b651756efbc261986e0ec6a2977ec44b42b314 100644
--- a/src/spaces-inl.h
+++ b/src/spaces-inl.h
@@ -152,6 +152,35 @@ 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 = 0xFFFFFFFF;
+  } else if (length_in_bytes > 0) {
+    intptr_t start_offset = OffsetFrom(start);
+    intptr_t end_offset = start_offset + length_in_bytes + kRegionSize - 1;
+    intptr_t start_region_addr = start_offset & ~kRegionAlignmentMask;
+    intptr_t end_region_addr = end_offset & ~kRegionAlignmentMask;
+    int start_region_index =
+        static_cast<int>(start_region_addr >> kRegionSizeLog2);
+ int end_region_index = static_cast<int>(end_region_addr >> kRegionSizeLog2);
+    const int mask = (1 << (kPageSizeBits - kRegionSizeLog2)) - 1;
+ for (int index = start_region_index; index < end_region_index; index++) {
+      result |= 1 << (index & 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: src/spaces.h
diff --git a/src/spaces.h b/src/spaces.h
index 32a3e6cb0e63a1263bd2c3532e669e71c8deafab..051ce37cf8969279144dde119ea1e689e44370d9 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -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);


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to