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

Unified Diff: src/mark-compact.cc

Issue 6321008: Introduce conservative sweeping. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 11 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
Index: src/mark-compact.cc
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 4a29c21df74c4c60ed4afaef491f45d42bd6bb17..05178f3a61798210b19872a87ae77d9115100eea 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -110,7 +110,8 @@ void MarkCompactCollector::CollectGarbage() {
// Check that swept all marked objects and
// null out the GC tracer.
- ASSERT(tracer_->marked_count() == 0);
+ // TODO(gc) does not work with conservative sweeping.
+ // ASSERT(tracer_->marked_count() == 0);
tracer_ = NULL;
}
@@ -135,6 +136,23 @@ static void VerifyMarkbitsAreClean() {
#endif
+static void ClearMarkbits(PagedSpace* space) {
+ PageIterator it(space, PageIterator::PAGES_IN_USE);
+
+ while (it.has_next()) {
+ Page* p = it.next();
+ p->markbits()->Clear();
+ }
+}
+
+static void ClearMarkbits() {
+ // We are sweeping code and map spaces presisely so clearing is not required.
Erik Corry 2011/01/19 13:46:48 presisely -> precisely,
Vyacheslav Egorov (Chromium) 2011/01/20 16:40:21 Done.
+ ClearMarkbits(Heap::old_pointer_space());
+ ClearMarkbits(Heap::old_data_space());
+ ClearMarkbits(Heap::cell_space());
+}
+
+
void MarkCompactCollector::Prepare(GCTracer* tracer) {
FLAG_flush_code = false;
FLAG_always_compact = false;
@@ -171,6 +189,8 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
Marking::ClearRange(new_space_bottom,
static_cast<int>(new_space_top - new_space_bottom));
+ ClearMarkbits();
+
#ifdef DEBUG
VerifyMarkbitsAreClean();
@@ -1718,7 +1738,164 @@ void MarkCompactCollector::SweepNewSpace(NewSpace* space) {
}
-void MarkCompactCollector::SweepSpace(PagedSpace* space) {
+INLINE(static uint32_t SweepFree(PagedSpace* space,
+ Page* p,
+ uint32_t free_start,
+ uint32_t region_end,
+ uint32_t* cells));
+
+
+static uint32_t SweepFree(PagedSpace* space,
+ Page* p,
+ uint32_t free_start,
+ uint32_t region_end,
+ uint32_t* cells) {
+ uint32_t free_cell = Page::MarkbitsBitmap::Index2Cell(free_start);
+ ASSERT(cells[free_cell] == 0);
+ while (free_cell < region_end && cells[free_cell] == 0) {
+ free_cell++;
+ }
+
+ if (free_cell >= region_end) {
+ return free_cell;
+ }
+
+ uint32_t free_end = Page::MarkbitsBitmap::Cell2Index(free_cell);
+ space->DeallocateBlock(p->Markbit2Address(free_start),
+ (free_end - free_start) << kPointerSizeLog2,
+ true);
+
+ return free_cell;
+}
+
+
+INLINE(static uint32_t NextCandidate(uint32_t cell,
+ uint32_t last_cell,
+ uint32_t* cells));
+
+
+static uint32_t NextCandidate(uint32_t cell,
+ uint32_t last_cell,
+ uint32_t* cells) {
+ do {
+ cell++;
+ } while (cell < last_cell && cells[cell] != 0);
+ return cell;
+}
+
+
+INLINE(static int SizeOfPreviousObject(Page* p,
+ uint32_t cell,
+ uint32_t* cells));
+
+
+static int SizeOfPreviousObject(Page* p,
+ uint32_t cell,
+ uint32_t* cells) {
+ ASSERT(cells[cell] == 0);
+ if (cells[cell - 1] == 0) return 0;
+
+ int clz = __builtin_clz(cells[cell - 1]) + 1;
Erik Corry 2011/01/19 13:46:48 Variable should be called leading_zeros
Vyacheslav Egorov (Chromium) 2011/01/20 16:40:21 Done.
+ Address addr =
+ p->Markbit2Address(Page::MarkbitsBitmap::Cell2Index(cell) - clz);
+ HeapObject* obj = HeapObject::FromAddress(addr);
+ ASSERT(obj->map()->IsMap());
+ return (obj->Size() >> kPointerSizeLog2) - clz;
+}
+
+
+static void SweepConservatively(PagedSpace* space,
+ Page* p,
+ Address* last_free_start) {
+ typedef Page::MarkbitsBitmap::CellType CellType;
+ Page::MarkbitsBitmap* markbits = p->markbits();
+ CellType* cells = markbits->cells();
+
+ uint32_t last_cell =
+ Page::MarkbitsBitmap::Index2Cell(
+ Page::MarkbitsBitmap::CellAlignIndex(
+ p->Address2Markbit(p->AllocationTop())));
+
+ uint32_t cell = Page::kFirstUsedCell;
Erik Corry 2011/01/19 13:46:48 See above.
+ uint32_t poluted_cell = Page::kFirstUsedCell;
Erik Corry 2011/01/19 13:46:48 poluted -> polluted
Vyacheslav Egorov (Chromium) 2011/01/20 16:40:21 Done.
+ if (cells[cell] == 0) {
+ poluted_cell = SweepFree(space,
+ p,
+ p->Address2Markbit(p->ObjectAreaStart()),
+ last_cell,
+ cells);
+
+ if (poluted_cell >= last_cell) {
+ // All cells are free.
+ *last_free_start = p->ObjectAreaStart();
+ return;
+ }
+ }
+
+ p->ClearFlag(Page::IS_CONTINIOUS);
+
+ ASSERT(cells[poluted_cell] != 0);
+ for (cell = NextCandidate(poluted_cell, last_cell, cells);
+ cell < last_cell;
+ cell = NextCandidate(poluted_cell, last_cell, cells)) {
+ ASSERT(cells[cell] == 0);
+
+ int size = SizeOfPreviousObject(p, cell, cells);
+ if (size <= 0) {
+ poluted_cell = SweepFree(space,
+ p,
+ Page::MarkbitsBitmap::Cell2Index(cell),
+ last_cell,
+ cells);
+ if (poluted_cell >= last_cell) {
+ // This free region is the last on the page.
+ *last_free_start = p->Markbit2Address(
+ Page::MarkbitsBitmap::Cell2Index(cell));
+ return;
+ }
+ } else {
+ // Skip cells covered by this object.
+ poluted_cell = cell +
+ Page::MarkbitsBitmap::Index2Cell(size - 1);
+ }
+ }
+}
+
+
+static void SweepPrecisely(PagedSpace* space, Page* p, Address* last_free_start) {
Erik Corry 2011/01/19 13:46:48 Lint?
Vyacheslav Egorov (Chromium) 2011/01/20 16:40:21 Done.
+ bool is_previous_alive = true;
+ Address free_start = NULL;
+ HeapObject* object;
+
+ for (Address current = p->ObjectAreaStart();
+ current < p->AllocationTop();
+ current += object->Size()) {
+ object = HeapObject::FromAddress(current);
+ if (Marking::IsMarked(object)) {
+ Marking::ClearMark(object);
+ MarkCompactCollector::tracer()->decrement_marked_count();
+
+ if (!is_previous_alive) { // Transition from free to live.
+ space->DeallocateBlock(free_start,
+ static_cast<int>(current - free_start),
+ true);
+ is_previous_alive = true;
+ }
+ } else {
+ MarkCompactCollector::ReportDeleteIfNeeded(object);
+ if (is_previous_alive) { // Transition from live to free.
+ free_start = current;
+ is_previous_alive = false;
+ }
+ }
+ }
+
+ if (!is_previous_alive) *last_free_start = free_start;
+}
+
+
+void MarkCompactCollector::SweepSpace(PagedSpace* space,
+ SweeperType sweeper) {
PageIterator it(space, PageIterator::PAGES_IN_USE);
// During sweeping of paged space we are trying to find longest sequences
@@ -1746,37 +1923,20 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space) {
while (it.has_next()) {
Page* p = it.next();
- bool is_previous_alive = true;
- Address free_start = NULL;
- HeapObject* object;
-
- for (Address current = p->ObjectAreaStart();
- current < p->AllocationTop();
- current += object->Size()) {
- object = HeapObject::FromAddress(current);
- if (Marking::IsMarked(object)) {
- Marking::ClearMark(object);
- MarkCompactCollector::tracer()->decrement_marked_count();
-
- if (!is_previous_alive) { // Transition from free to live.
- space->DeallocateBlock(free_start,
- static_cast<int>(current - free_start),
- true);
- is_previous_alive = true;
- }
- } else {
- MarkCompactCollector::ReportDeleteIfNeeded(object);
- if (is_previous_alive) { // Transition from live to free.
- free_start = current;
- is_previous_alive = false;
- }
- }
- // The object is now unmarked for the call to Size() at the top of the
- // loop.
+ Address free_start = p->AllocationTop();
+
+ if (sweeper == CONSERVATIVE) {
+ SweepConservatively(space, p, &free_start);
+ p->set_linearity_boundary(free_start);
+ } else {
+ ASSERT(sweeper == PRECISE);
+ SweepPrecisely(space, p, &free_start);
}
- bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop())
- || (!is_previous_alive && free_start == p->ObjectAreaStart());
+ bool page_is_empty = (p->ObjectAreaStart() == free_start);
+ bool is_previous_alive = (free_start == p->AllocationTop());
+
+ ASSERT(free_start <= p->AllocationTop());
if (page_is_empty) {
// This page is empty. Check whether we are in the middle of
@@ -1830,7 +1990,7 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space) {
// Last used pages in space are empty. We can move allocation top backwards
// to the beginning of first empty page.
ASSERT(prev == space->AllocationTopPage());
-
+ space->FreePages(prec_first_empty_page, prev);
new_allocation_top = first_empty_page->ObjectAreaStart();
}
@@ -1869,21 +2029,26 @@ void MarkCompactCollector::SweepSpaces() {
// the map space last because freeing non-live maps overwrites them and
// the other spaces rely on possibly non-live maps to get the sizes for
// non-live objects.
- SweepSpace(Heap::old_pointer_space());
- SweepSpace(Heap::old_data_space());
- SweepSpace(Heap::code_space());
- SweepSpace(Heap::cell_space());
+ SweepSpace(Heap::old_pointer_space(), CONSERVATIVE);
+ SweepSpace(Heap::old_data_space(), CONSERVATIVE);
+ SweepSpace(Heap::code_space(), PRECISE);
+ // TODO(gc): implement specialized sweeper for cell space.
+ SweepSpace(Heap::cell_space(), CONSERVATIVE);
{ GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
SweepNewSpace(Heap::new_space());
}
- SweepSpace(Heap::map_space());
+ // TODO(gc): ClearNonLiveTransitions depends on precise sweeping of
+ // map space to detect whether unmarked map became dead in this
+ // collection on in one of the previous ones.
Erik Corry 2011/01/19 13:46:48 on -> or
Vyacheslav Egorov (Chromium) 2011/01/20 16:40:21 Done.
+ // Implement specialized sweeper for map space.
Erik Corry 2011/01/19 13:46:48 Missing TODO?
Vyacheslav Egorov (Chromium) 2011/01/20 16:40:21 Done.
+ SweepSpace(Heap::map_space(), PRECISE);
Heap::IterateDirtyRegions(Heap::map_space(),
&Heap::IteratePointersInDirtyMapsRegion,
&UpdatePointerToNewGen,
Heap::WATERMARK_SHOULD_BE_VALID);
- ASSERT(live_map_objects_size_ == Heap::map_space()->Size());
+ ASSERT(live_map_objects_size_ <= Heap::map_space()->Size());
}
@@ -1941,6 +2106,10 @@ void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
if (obj->IsCode()) {
PROFILE(CodeDeleteEvent(obj->address()));
} else if (obj->IsJSFunction()) {
+ // TODO(gc): we are sweeping old pointer space conservatively thus
+ // we can't notify attached profiler about death of functions.
+ // Consider disabling conservative sweeping when profiler
+ // is enabled.
PROFILE(FunctionDeleteEvent(obj->address()));
}
#endif

Powered by Google App Engine
This is Rietveld 408576698