Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1821)

Unified Diff: src/store-buffer.cc

Issue 7044082: Minor cleanup of StoreBuffer related heap iteration methods. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/store-buffer.h ('K') | « src/store-buffer.h ('k') | src/v8globals.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/store-buffer.cc
diff --git a/src/store-buffer.cc b/src/store-buffer.cc
index da3bfd41f2e5d056cfd979a318179ba95245fa56..49f6917821c43d6469376372b4dc41e990bf405b 100644
--- a/src/store-buffer.cc
+++ b/src/store-buffer.cc
@@ -350,7 +350,56 @@ void StoreBuffer::GCPrologue(GCType type, GCCallbackFlags flags) {
}
+#ifdef DEBUG
+static void DummyScavengePointer(HeapObject** p, HeapObject* o) {
+ // Do nothing.
+}
+
+
+void StoreBuffer::VerifyPointers(PagedSpace* space,
+ RegionCallback region_callback) {
+ PageIterator it(space);
+
+ while (it.has_next()) {
+ Page* page = it.next();
+ FindPointersToNewSpaceOnPage(
+ reinterpret_cast<PagedSpace*>(page->owner()),
+ page,
+ region_callback,
+ &DummyScavengePointer);
+ }
+}
+
+
+void StoreBuffer::VerifyPointers(LargeObjectSpace* space) {
+ LargeObjectIterator it(space);
+ for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
+ if (object->IsFixedArray()) {
+ Address slot_address = object->address();
+ Address end = object->address() + object->Size();
+
+ while (slot_address < end) {
+ HeapObject** slot = reinterpret_cast<HeapObject**>(slot_address);
+ // When we are not in GC the Heap::InNewSpace() predicate
+ // checks that pointers which satisfy predicate point into
+ // the active semispace.
+ heap_->InNewSpace(*slot);
+ slot_address += kPointerSize;
+ }
+ }
+ }
+}
+#endif
+
+
void StoreBuffer::Verify() {
+#ifdef DEBUG
+ VerifyPointers(heap_->old_pointer_space(),
+ &StoreBuffer::FindPointersToNewSpaceInRegion);
+ VerifyPointers(heap_->map_space(),
+ &StoreBuffer::FindPointersToNewSpaceInMapsRegion);
+ VerifyPointers(heap_->lo_space());
+#endif
}
@@ -361,7 +410,153 @@ void StoreBuffer::GCEpilogue(GCType type, GCCallbackFlags flags) {
}
-void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback callback) {
+void StoreBuffer::FindPointersToNewSpaceInRegion(
+ Address start, Address end, ObjectSlotCallback slot_callback) {
+ for (Address slot_address = start;
+ slot_address < end;
+ slot_address += kPointerSize) {
+ Object** slot = reinterpret_cast<Object**>(slot_address);
+ if (heap_->InNewSpace(*slot)) {
+ HeapObject* object = reinterpret_cast<HeapObject*>(*slot);
+ ASSERT(object->IsHeapObject());
+ slot_callback(reinterpret_cast<HeapObject**>(slot), object);
+ if (heap_->InNewSpace(*slot)) {
+ EnterDirectlyIntoStoreBuffer(slot_address);
+ }
+ }
+ }
+}
+
+
+// Compute start address of the first map following given addr.
+static inline Address MapStartAlign(Address addr) {
+ Address page = Page::FromAddress(addr)->ObjectAreaStart();
+ return page + (((addr - page) + (Map::kSize - 1)) / Map::kSize * Map::kSize);
+}
+
+
+// Compute end address of the first map preceding given addr.
+static inline Address MapEndAlign(Address addr) {
+ Address page = Page::FromAllocationTop(addr)->ObjectAreaStart();
+ return page + ((addr - page) / Map::kSize * Map::kSize);
+}
+
+
+void StoreBuffer::FindPointersToNewSpaceInMaps(
+ Address start,
+ Address end,
+ ObjectSlotCallback slot_callback) {
+ ASSERT(MapStartAlign(start) == start);
+ ASSERT(MapEndAlign(end) == end);
+
+ Address map_address = start;
+ while (map_address < end) {
+ ASSERT(!heap_->InNewSpace(Memory::Object_at(map_address)));
+ ASSERT(Memory::Object_at(map_address)->IsMap());
+
+ Address pointer_fields_start = map_address + Map::kPointerFieldsBeginOffset;
+ Address pointer_fields_end = map_address + Map::kPointerFieldsEndOffset;
+
+ FindPointersToNewSpaceInRegion(pointer_fields_start,
+ pointer_fields_end,
+ slot_callback);
+ map_address += Map::kSize;
+ }
+}
+
+
+void StoreBuffer::FindPointersToNewSpaceInMapsRegion(
+ Address start,
+ Address end,
+ ObjectSlotCallback slot_callback) {
+ Address map_aligned_start = MapStartAlign(start);
+ Address map_aligned_end = MapEndAlign(end);
+
+ ASSERT(map_aligned_start == start);
+ ASSERT(map_aligned_end == end);
+
+ FindPointersToNewSpaceInMaps(map_aligned_start,
+ map_aligned_end,
+ slot_callback);
+}
+
+
+// This function iterates over all the pointers in a paged space in the heap,
+// looking for pointers into new space. Within the pages there may be dead
+// objects that have not been overwritten by free spaces or fillers because of
+// lazy sweeping. These dead objects may not contain pointers to new space.
+// The garbage areas that have been swept properly (these will normally be the
+// large ones) will be marked with free space and filler map words. In
+// addition any area that has never been used at all for object allocation must
+// be marked with a free space or filler. Because the free space and filler
+// maps do not move we can always recognize these even after a compaction.
+// Normal objects like FixedArrays and JSObjects should not contain references
+// to these maps. The special garbage section (see comment in spaces.h) is
+// skipped since it can contain absolutely anything. Any objects that are
+// allocated during iteration may or may not be visited by the iteration, but
+// they will not be partially visited.
+void StoreBuffer::FindPointersToNewSpaceOnPage(
+ PagedSpace* space,
+ Page* page,
+ RegionCallback region_callback,
+ ObjectSlotCallback slot_callback) {
+ Address visitable_start = page->ObjectAreaStart();
+ Address end_of_page = page->ObjectAreaEnd();
+
+ Address visitable_end = visitable_start;
+
+ Object* free_space_map = heap_->free_space_map();
+ Object* two_pointer_filler_map = heap_->two_pointer_filler_map();
+
+ while (visitable_end < end_of_page) {
+ Object* o = *reinterpret_cast<Object**>(visitable_end);
+ // Skip fillers but not things that look like fillers in the special
+ // garbage section which can contain anything.
+ if (o == free_space_map ||
+ o == two_pointer_filler_map ||
+ visitable_end == space->top()) {
+ if (visitable_start != visitable_end) {
+ // After calling this the special garbage section may have moved.
+ (this->*region_callback)(visitable_start,
+ visitable_end,
+ slot_callback);
+ if (visitable_end >= space->top() && visitable_end < space->limit()) {
+ visitable_end = space->limit();
+ visitable_start = visitable_end;
+ continue;
+ }
+ }
+ if (visitable_end == space->top() && visitable_end != space->limit()) {
+ visitable_start = visitable_end = space->limit();
+ } else {
+ // At this point we are either at the start of a filler or we are at
+ // the point where the space->top() used to be before the
+ // visit_pointer_region call above. Either way we can skip the
+ // object at the current spot: We don't promise to visit objects
+ // allocated during heap traversal, and if space->top() moved then it
+ // must be because an object was allocated at this point.
+ visitable_start =
+ visitable_end + HeapObject::FromAddress(visitable_end)->Size();
+ visitable_end = visitable_start;
+ }
+ } else {
+ ASSERT(o != free_space_map);
+ ASSERT(o != two_pointer_filler_map);
+ ASSERT(visitable_end < space->top() || visitable_end >= space->limit());
+ visitable_end += kPointerSize;
+ }
+ }
+ ASSERT(visitable_end == end_of_page);
+ if (visitable_start != visitable_end) {
+ (this->*region_callback)(visitable_start,
+ visitable_end,
+ slot_callback);
+ }
+}
+
+
+
+void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
// We do not sort or remove duplicated entries from the store buffer because
// we expect that callback will rebuild the store buffer thus removing
// all duplicates and pointers to old space.
@@ -375,12 +570,15 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback callback) {
#ifdef DEBUG
Address* saved_top = old_top_;
#endif
- Object** cell = reinterpret_cast<Object**>(*current);
- Object* object = *cell;
+ Object** slot = reinterpret_cast<Object**>(*current);
+ Object* object = *slot;
// May be invalid if object is not in new space.
Erik Corry 2011/06/13 08:16:39 It may well be me that wrote this, but I can't rem
HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
if (heap_->InFromSpace(object)) {
- callback(reinterpret_cast<HeapObject**>(cell), heap_object);
+ slot_callback(reinterpret_cast<HeapObject**>(slot), heap_object);
+ if (heap_->InNewSpace(*slot)) {
+ EnterDirectlyIntoStoreBuffer(reinterpret_cast<Address>(slot));
+ }
}
ASSERT(old_top_ == saved_top + 1 || old_top_ == saved_top);
}
@@ -410,18 +608,18 @@ void StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback callback) {
HeapObject* array = large_page->GetObject();
ASSERT(array->IsFixedArray());
Address start = array->address();
- Address object_end = start + array->Size();
- heap_->IteratePointersToNewSpace(heap_, start, object_end, callback);
+ Address end = start + array->Size();
+ FindPointersToNewSpaceInRegion(start, end, slot_callback);
} else {
Page* page = reinterpret_cast<Page*>(chunk);
PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
- heap_->IteratePointersOnPage(
+ FindPointersToNewSpaceOnPage(
owner,
+ page,
(owner == heap_->map_space() ?
- &Heap::IteratePointersFromMapsToNewSpace :
- &Heap::IteratePointersToNewSpace),
- callback,
- page);
+ &StoreBuffer::FindPointersToNewSpaceInMapsRegion :
+ &StoreBuffer::FindPointersToNewSpaceInRegion),
+ slot_callback);
}
}
}
« src/store-buffer.h ('K') | « src/store-buffer.h ('k') | src/v8globals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698