PrintF("Sweeping 0x%" V8PRIxPTR " lazily postponed.\n",
reinterpret_cast<intptr_t>(p));
}
+ space->MarkPageForLazySweeping(p);
continue;
}
: Space(heap, id, executable),
free_list_(this),
was_swept_conservatively_(false),
- first_unswept_page_(Page::FromAddress(NULL)) {
+ first_unswept_page_(Page::FromAddress(NULL)),
+ unswept_free_bytes_(0) {
max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize)
* Page::kObjectAreaSize;
accounting_stats_.Clear();
} while (p != anchor());
}
first_unswept_page_ = Page::FromAddress(NULL);
+ unswept_free_bytes_ = 0;
// Clear the free list before a full GC---it will be rebuilt afterward.
free_list_.Reset();
PrintF("Sweeping 0x%" V8PRIxPTR " lazily advanced.\n",
reinterpret_cast<intptr_t>(p));
}
+ unswept_free_bytes_ -= (Page::kObjectAreaSize - p->LiveBytes());
freed_bytes += MarkCompactCollector::SweepConservatively(this, p);
}
p = next_page;
// linear allocation area (between top and limit) are also counted here.
virtual intptr_t Size() { return accounting_stats_.Size(); }
- // As size, but the bytes in the current linear allocation area are not
- // included.
- virtual intptr_t SizeOfObjects() { return Size() - (limit() - top()); }
+ // As size, but the bytes in lazily swept pages are estimated and the bytes
+ // in the current linear allocation area are not included.
+ virtual intptr_t SizeOfObjects() {
+ ASSERT(!IsSweepingComplete() || (unswept_free_bytes_ == 0));
+ return Size() - unswept_free_bytes_ - (limit() - top());
+ }
// Wasted bytes in this space. These are just the bytes that were thrown away
// due to being too small to use for allocation. They do not include the
virtual intptr_t Waste() { return accounting_stats_.Waste(); }
// Returns the allocation pointer in this space.
- Address top() {
- return allocation_info_.top;
- }
+ Address top() { return allocation_info_.top; }
Address limit() { return allocation_info_.limit; }
// Allocate the requested number of bytes in the space if possible, return a
}
void SetPagesToSweep(Page* first) {
+ ASSERT(unswept_free_bytes_ == 0);
if (first == &anchor_) first = NULL;
first_unswept_page_ = first;
}
+ void MarkPageForLazySweeping(Page* p) {
+ unswept_free_bytes_ += (Page::kObjectAreaSize - p->LiveBytes());
+ }
+
bool AdvanceSweeper(intptr_t bytes_to_sweep);
bool IsSweepingComplete() {
bool was_swept_conservatively_;
+ // The first page to be swept when the lazy sweeper advances. Is set
+ // to NULL when all pages have been swept.
Page* first_unswept_page_;
+ // The number of free bytes which could be reclaimed by advancing the
+ // lazy sweeper. This is only an estimation because lazy sweeping is
+ // done conservatively.
+ intptr_t unswept_free_bytes_;
+
// Expands the space by allocating a fixed number of pages. Returns false if
// it cannot allocate requested number of pages from OS, or if the hard heap
// size limit has been hit.
}
+TEST(TestSizeOfObjects) {
+ v8::V8::Initialize();
+
+ // Get initial heap size after several full GCs, which will stabilize
+ // the heap size and return with sweeping finished completely.
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+ CHECK(HEAP->old_pointer_space()->IsSweepingComplete());
+ intptr_t initial_size = HEAP->SizeOfObjects();
+
+ {
+ // Allocate objects on several different old-space pages so that
+ // lazy sweeping kicks in for subsequent GC runs.
+ AlwaysAllocateScope always_allocate;
+ intptr_t filler_size = FixedArray::SizeFor(8192);
+ for (int i = 1; i <= 100; i++) {
+ HEAP->AllocateFixedArray(8192, TENURED)->ToObjectChecked();
+ CHECK_EQ(initial_size + i * filler_size, HEAP->SizeOfObjects());
+ }
+ }
+
+ // The heap size should go back to initial size after a full GC, even
+ // though sweeping didn't finish yet.
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags);
+ CHECK(!HEAP->old_pointer_space()->IsSweepingComplete());
+ CHECK_EQ(initial_size, HEAP->SizeOfObjects());
+
+ // Advancing the sweeper step-wise should not change the heap size.
+ while (!HEAP->old_pointer_space()->IsSweepingComplete()) {
+ HEAP->old_pointer_space()->AdvanceSweeper(KB);
+ CHECK_EQ(initial_size, HEAP->SizeOfObjects());
+ }
+}
+
+
TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
InitializeVM();
HEAP->EnsureHeapIsIterable();