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