// -----------------------------------------------------------------------------
// PageIterator
-PageIterator::PageIterator(PagedSpace* space, Mode mode) {
- cur_page_ = space->first_page_;
+PageIterator::PageIterator(PagedSpace* space, Mode mode) : space_(space) {
+ prev_page_ = NULL;
switch (mode) {
case PAGES_IN_USE:
- stop_page_ = space->AllocationTopPage()->next_page();
+ stop_page_ = space->AllocationTopPage();
break;
case PAGES_USED_BY_MC:
- stop_page_ = space->MCRelocationTopPage()->next_page();
+ stop_page_ = space->MCRelocationTopPage();
break;
case ALL_PAGES:
- stop_page_ = Page::FromAddress(NULL);
+ stop_page_ = space->last_page_;
break;
default:
UNREACHABLE();
accounting_stats_.ExpandSpace(num_pages * Page::kObjectAreaSize);
ASSERT(Capacity() <= max_capacity_);
+ // Sequentially initialize remembered sets in the newly allocated
+ // pages and cache the current last page in the space.
for (Page* p = first_page_; p->is_valid(); p = p->next_page()) {
p->ClearRSet();
+ last_page_ = p;
}
// Use first_page_ for allocation.
MemoryAllocator::SetNextPage(last_page, p);
- // Clear remembered set of new pages.
+ // Sequentially clear remembered set of new pages and and cache the
+ // new last page in the space.
while (p->is_valid()) {
p->ClearRSet();
+ last_page_ = p;
p = p->next_page();
}
Page* p = MemoryAllocator::FreePages(last_page_to_keep->next_page());
MemoryAllocator::SetNextPage(last_page_to_keep, p);
- // Since pages are only freed in whole chunks, we may have kept more than
- // pages_to_keep.
+ // Since pages are only freed in whole chunks, we may have kept more
+ // than pages_to_keep. Count the extra pages and cache the new last
+ // page in the space.
while (p->is_valid()) {
pages_to_keep++;
+ last_page_ = p;
p = p->next_page();
}
//
// A HeapObjectIterator iterates objects from a given address to the
// top of a space. The given address must be below the current
-// allocation pointer (space top). If the space top changes during
-// iteration (because of allocating new objects), the iterator does
-// not iterate new objects. The caller function must create a new
-// iterator starting from the old top in order to visit these new
-// objects. Heap::Scavenage() is such an example.
+// allocation pointer (space top). There are some caveats.
+//
+// (1) If the space top changes upward during iteration (because of
+// allocating new objects), the iterator does not iterate objects
+// above the original space top. The caller must create a new
+// iterator starting from the old top in order to visit these new
+// objects. Heap::Scavenge() is such an example.
+//
+// (2) If new objects are allocated below the original allocation top
+// (e.g., free-list allocation in paged spaces), the new objects
+// may or may not be iterated depending on their position with
+// respect to the current point of iteration.
+//
+// (3) The space top should not change downward during iteration,
+// otherwise the iterator will return not-necessarily-valid
+// objects.
class HeapObjectIterator: public ObjectIterator {
public:
// -----------------------------------------------------------------------------
-// A PageIterator iterates pages in a space.
+// A PageIterator iterates the pages in a paged space.
//
// The PageIterator class provides three modes for iterating pages in a space:
-// PAGES_IN_USE iterates pages that are in use by the allocator;
-// PAGES_USED_BY_GC iterates pages that hold relocated objects during a
-// mark-compact collection;
+// PAGES_IN_USE iterates pages containing allocated objects.
+// PAGES_USED_BY_MC iterates pages that hold relocated objects during a
+// mark-compact collection.
// ALL_PAGES iterates all pages in the space.
+//
+// There are some caveats.
+//
+// (1) If the space expands during iteration, new pages will not be
+// returned by the iterator in any mode.
+//
+// (2) If new objects are allocated during iteration, they will appear
+// in pages returned by the iterator. Allocation may cause the
+// allocation pointer or MC allocation pointer in the last page to
+// change between constructing the iterator and iterating the last
+// page.
+//
+// (3) The space should not shrink during iteration, otherwise the
+// iterator will return deallocated pages.
class PageIterator BASE_EMBEDDED {
public:
- enum Mode {PAGES_IN_USE, PAGES_USED_BY_MC, ALL_PAGES};
+ enum Mode {
+ PAGES_IN_USE,
+ PAGES_USED_BY_MC,
+ ALL_PAGES
+ };
PageIterator(PagedSpace* space, Mode mode);
inline Page* next();
private:
- Page* cur_page_; // next page to return
- Page* stop_page_; // page where to stop
+ PagedSpace* space_;
+ Page* prev_page_; // Previous page returned.
+ Page* stop_page_; // Page to stop at (last page returned by the iterator).
};
// The first page in this space.
Page* first_page_;
+ // The last page in this space. Initially set in Setup, updated in
+ // Expand and Shrink.
+ Page* last_page_;
+
// Normal allocation information.
AllocationInfo allocation_info_;