diff options
Diffstat (limited to 'deps/v8/src/spaces.cc')
-rw-r--r-- | deps/v8/src/spaces.cc | 444 |
1 files changed, 132 insertions, 312 deletions
diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc index 6b6d926e2..1d868e9ac 100644 --- a/deps/v8/src/spaces.cc +++ b/deps/v8/src/spaces.cc @@ -41,6 +41,7 @@ namespace internal { && (info).top <= (space).high() \ && (info).limit == (space).high()) +intptr_t Page::watermark_invalidated_mark_ = Page::WATERMARK_INVALIDATED; // ---------------------------------------------------------------------------- // HeapObjectIterator @@ -139,13 +140,6 @@ PageIterator::PageIterator(PagedSpace* space, Mode mode) : space_(space) { // ----------------------------------------------------------------------------- -// Page - -#ifdef DEBUG -Page::RSetState Page::rset_state_ = Page::IN_USE; -#endif - -// ----------------------------------------------------------------------------- // CodeRange List<CodeRange::FreeBlock> CodeRange::free_list_(0); @@ -524,7 +518,10 @@ Page* MemoryAllocator::InitializePagesInChunk(int chunk_id, int pages_in_chunk, for (int i = 0; i < pages_in_chunk; i++) { Page* p = Page::FromAddress(page_addr); p->opaque_header = OffsetFrom(page_addr + Page::kPageSize) | chunk_id; + p->InvalidateWatermark(true); p->SetIsLargeObjectPage(false); + p->SetAllocationWatermark(p->ObjectAreaStart()); + p->SetCachedAllocationWatermark(p->ObjectAreaStart()); page_addr += Page::kPageSize; } @@ -681,6 +678,7 @@ Page* MemoryAllocator::RelinkPagesInChunk(int chunk_id, p->opaque_header = OffsetFrom(page_addr + Page::kPageSize) | chunk_id; page_addr += Page::kPageSize; + p->InvalidateWatermark(true); if (p->WasInUseBeforeMC()) { *last_page_in_use = p; } @@ -744,10 +742,10 @@ bool PagedSpace::Setup(Address start, size_t size) { accounting_stats_.ExpandSpace(num_pages * Page::kObjectAreaSize); ASSERT(Capacity() <= max_capacity_); - // Sequentially initialize remembered sets in the newly allocated + // Sequentially clear region marks 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(); + p->SetRegionMarks(Page::kAllRegionsCleanMarks); last_page_ = p; } @@ -794,10 +792,10 @@ void PagedSpace::Unprotect() { #endif -void PagedSpace::ClearRSet() { +void PagedSpace::MarkAllPagesClean() { PageIterator it(this, PageIterator::ALL_PAGES); while (it.has_next()) { - it.next()->ClearRSet(); + it.next()->SetRegionMarks(Page::kAllRegionsCleanMarks); } } @@ -900,7 +898,8 @@ HeapObject* PagedSpace::SlowMCAllocateRaw(int size_in_bytes) { // of forwarding addresses is as an offset in terms of live bytes, so we // need quick access to the allocation top of each page to decode // forwarding addresses. - current_page->mc_relocation_top = mc_forwarding_info_.top; + current_page->SetAllocationWatermark(mc_forwarding_info_.top); + current_page->next_page()->InvalidateWatermark(true); SetAllocationInfo(&mc_forwarding_info_, current_page->next_page()); return AllocateLinearly(&mc_forwarding_info_, size_in_bytes); } @@ -928,10 +927,10 @@ bool PagedSpace::Expand(Page* last_page) { MemoryAllocator::SetNextPage(last_page, p); - // Sequentially clear remembered set of new pages and and cache the + // Sequentially clear region marks of new pages and and cache the // new last page in the space. while (p->is_valid()) { - p->ClearRSet(); + p->SetRegionMarks(Page::kAllRegionsCleanMarks); last_page_ = p; p = p->next_page(); } @@ -1030,16 +1029,11 @@ void PagedSpace::Verify(ObjectVisitor* visitor) { if (above_allocation_top) { // We don't care what's above the allocation top. } else { - // Unless this is the last page in the space containing allocated - // objects, the allocation top should be at a constant offset from the - // object area end. Address top = current_page->AllocationTop(); if (current_page == top_page) { ASSERT(top == allocation_info_.top); // The next page will be above the allocation top. above_allocation_top = true; - } else { - ASSERT(top == PageAllocationLimit(current_page)); } // It should be packed with objects from the bottom to the top. @@ -1060,8 +1054,8 @@ void PagedSpace::Verify(ObjectVisitor* visitor) { object->Verify(); // All the interior pointers should be contained in the heap and - // have their remembered set bits set if required as determined - // by the visitor. + // have page regions covering intergenerational references should be + // marked dirty. int size = object->Size(); object->IterateBody(map->instance_type(), size, visitor); @@ -1120,7 +1114,7 @@ bool NewSpace::Setup(Address start, int size) { start_ = start; address_mask_ = ~(size - 1); - object_mask_ = address_mask_ | kHeapObjectTag; + object_mask_ = address_mask_ | kHeapObjectTagMask; object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; allocation_info_.top = to_space_.low(); @@ -1324,7 +1318,7 @@ bool SemiSpace::Setup(Address start, start_ = start; address_mask_ = ~(maximum_capacity - 1); - object_mask_ = address_mask_ | kHeapObjectTag; + object_mask_ = address_mask_ | kHeapObjectTagMask; object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; age_mark_ = start_; @@ -1634,7 +1628,7 @@ void FreeListNode::set_size(int size_in_bytes) { // If the block is too small (eg, one or two words), to hold both a size // field and a next pointer, we give it a filler map that gives it the // correct size. - if (size_in_bytes > ByteArray::kAlignedSize) { + if (size_in_bytes > ByteArray::kHeaderSize) { set_map(Heap::raw_unchecked_byte_array_map()); // Can't use ByteArray::cast because it fails during deserialization. ByteArray* this_as_byte_array = reinterpret_cast<ByteArray*>(this); @@ -1831,7 +1825,7 @@ FixedSizeFreeList::FixedSizeFreeList(AllocationSpace owner, int object_size) void FixedSizeFreeList::Reset() { available_ = 0; - head_ = NULL; + head_ = tail_ = NULL; } @@ -1843,8 +1837,13 @@ void FixedSizeFreeList::Free(Address start) { ASSERT(!MarkCompactCollector::IsCompacting()); FreeListNode* node = FreeListNode::FromAddress(start); node->set_size(object_size_); - node->set_next(head_); - head_ = node->address(); + node->set_next(NULL); + if (head_ == NULL) { + tail_ = head_ = node->address(); + } else { + FreeListNode::FromAddress(tail_)->set_next(node->address()); + tail_ = node->address(); + } available_ += object_size_; } @@ -1907,15 +1906,14 @@ void OldSpace::MCCommitRelocationInfo() { Page* p = it.next(); // Space below the relocation pointer is allocated. computed_size += - static_cast<int>(p->mc_relocation_top - p->ObjectAreaStart()); + static_cast<int>(p->AllocationWatermark() - p->ObjectAreaStart()); if (it.has_next()) { - // Free the space at the top of the page. We cannot use - // p->mc_relocation_top after the call to Free (because Free will clear - // remembered set bits). + // Free the space at the top of the page. int extra_size = - static_cast<int>(p->ObjectAreaEnd() - p->mc_relocation_top); + static_cast<int>(p->ObjectAreaEnd() - p->AllocationWatermark()); if (extra_size > 0) { - int wasted_bytes = free_list_.Free(p->mc_relocation_top, extra_size); + int wasted_bytes = free_list_.Free(p->AllocationWatermark(), + extra_size); // The bytes we have just "freed" to add to the free list were // already accounted as available. accounting_stats_.WasteBytes(wasted_bytes); @@ -1963,7 +1961,10 @@ void PagedSpace::FreePages(Page* prev, Page* last) { // Clean them up. do { - first->ClearRSet(); + first->InvalidateWatermark(true); + first->SetAllocationWatermark(first->ObjectAreaStart()); + first->SetCachedAllocationWatermark(first->ObjectAreaStart()); + first->SetRegionMarks(Page::kAllRegionsCleanMarks); first = first->next_page(); } while (first != NULL); @@ -2003,6 +2004,7 @@ void PagedSpace::PrepareForMarkCompact(bool will_compact) { // Current allocation top points to a page which is now in the middle // of page list. We should move allocation top forward to the new last // used page so various object iterators will continue to work properly. + last_in_use->SetAllocationWatermark(last_in_use->AllocationTop()); int size_in_bytes = static_cast<int>(PageAllocationLimit(last_in_use) - last_in_use->AllocationTop()); @@ -2035,6 +2037,7 @@ void PagedSpace::PrepareForMarkCompact(bool will_compact) { int size_in_bytes = static_cast<int>(PageAllocationLimit(p) - p->ObjectAreaStart()); + p->SetAllocationWatermark(p->ObjectAreaStart()); Heap::CreateFillerObjectAt(p->ObjectAreaStart(), size_in_bytes); } } @@ -2066,6 +2069,7 @@ bool PagedSpace::ReserveSpace(int bytes) { if (!reserved_page->is_valid()) return false; } ASSERT(TopPageOf(allocation_info_)->next_page()->is_valid()); + TopPageOf(allocation_info_)->next_page()->InvalidateWatermark(true); SetAllocationInfo(&allocation_info_, TopPageOf(allocation_info_)->next_page()); return true; @@ -2100,7 +2104,20 @@ HeapObject* OldSpace::SlowAllocateRaw(int size_in_bytes) { accounting_stats_.WasteBytes(wasted_bytes); if (!result->IsFailure()) { accounting_stats_.AllocateBytes(size_in_bytes); - return HeapObject::cast(result); + + HeapObject* obj = HeapObject::cast(result); + Page* p = Page::FromAddress(obj->address()); + + if (obj->address() >= p->AllocationWatermark()) { + // There should be no hole between the allocation watermark + // and allocated object address. + // Memory above the allocation watermark was not swept and + // might contain garbage pointers to new space. + ASSERT(obj->address() == p->AllocationWatermark()); + p->SetAllocationWatermark(obj->address() + size_in_bytes); + } + + return obj; } } @@ -2123,6 +2140,7 @@ HeapObject* OldSpace::SlowAllocateRaw(int size_in_bytes) { void OldSpace::PutRestOfCurrentPageOnFreeList(Page* current_page) { + current_page->SetAllocationWatermark(allocation_info_.top); int free_size = static_cast<int>(current_page->ObjectAreaEnd() - allocation_info_.top); if (free_size > 0) { @@ -2133,6 +2151,7 @@ void OldSpace::PutRestOfCurrentPageOnFreeList(Page* current_page) { void FixedSpace::PutRestOfCurrentPageOnFreeList(Page* current_page) { + current_page->SetAllocationWatermark(allocation_info_.top); int free_size = static_cast<int>(current_page->ObjectAreaEnd() - allocation_info_.top); // In the fixed space free list all the free list items have the right size. @@ -2152,8 +2171,10 @@ void FixedSpace::PutRestOfCurrentPageOnFreeList(Page* current_page) { HeapObject* OldSpace::AllocateInNextPage(Page* current_page, int size_in_bytes) { ASSERT(current_page->next_page()->is_valid()); + Page* next_page = current_page->next_page(); + next_page->ClearGCFields(); PutRestOfCurrentPageOnFreeList(current_page); - SetAllocationInfo(&allocation_info_, current_page->next_page()); + SetAllocationInfo(&allocation_info_, next_page); return AllocateLinearly(&allocation_info_, size_in_bytes); } @@ -2296,160 +2317,12 @@ void OldSpace::ReportStatistics() { PrintF(" capacity: %d, waste: %d, available: %d, %%%d\n", Capacity(), Waste(), Available(), pct); - // Report remembered set statistics. - int rset_marked_pointers = 0; - int rset_marked_arrays = 0; - int rset_marked_array_elements = 0; - int cross_gen_pointers = 0; - int cross_gen_array_elements = 0; - - PageIterator page_it(this, PageIterator::PAGES_IN_USE); - while (page_it.has_next()) { - Page* p = page_it.next(); - - for (Address rset_addr = p->RSetStart(); - rset_addr < p->RSetEnd(); - rset_addr += kIntSize) { - int rset = Memory::int_at(rset_addr); - if (rset != 0) { - // Bits were set - int intoff = - static_cast<int>(rset_addr - p->address() - Page::kRSetOffset); - int bitoff = 0; - for (; bitoff < kBitsPerInt; ++bitoff) { - if ((rset & (1 << bitoff)) != 0) { - int bitpos = intoff*kBitsPerByte + bitoff; - Address slot = p->OffsetToAddress(bitpos << kObjectAlignmentBits); - Object** obj = reinterpret_cast<Object**>(slot); - if (*obj == Heap::raw_unchecked_fixed_array_map()) { - rset_marked_arrays++; - FixedArray* fa = FixedArray::cast(HeapObject::FromAddress(slot)); - - rset_marked_array_elements += fa->length(); - // Manually inline FixedArray::IterateBody - Address elm_start = slot + FixedArray::kHeaderSize; - Address elm_stop = elm_start + fa->length() * kPointerSize; - for (Address elm_addr = elm_start; - elm_addr < elm_stop; elm_addr += kPointerSize) { - // Filter non-heap-object pointers - Object** elm_p = reinterpret_cast<Object**>(elm_addr); - if (Heap::InNewSpace(*elm_p)) - cross_gen_array_elements++; - } - } else { - rset_marked_pointers++; - if (Heap::InNewSpace(*obj)) - cross_gen_pointers++; - } - } - } - } - } - } - - pct = rset_marked_pointers == 0 ? - 0 : cross_gen_pointers * 100 / rset_marked_pointers; - PrintF(" rset-marked pointers %d, to-new-space %d (%%%d)\n", - rset_marked_pointers, cross_gen_pointers, pct); - PrintF(" rset_marked arrays %d, ", rset_marked_arrays); - PrintF(" elements %d, ", rset_marked_array_elements); - pct = rset_marked_array_elements == 0 ? 0 - : cross_gen_array_elements * 100 / rset_marked_array_elements; - PrintF(" pointers to new space %d (%%%d)\n", cross_gen_array_elements, pct); - PrintF(" total rset-marked bits %d\n", - (rset_marked_pointers + rset_marked_arrays)); - pct = (rset_marked_pointers + rset_marked_array_elements) == 0 ? 0 - : (cross_gen_pointers + cross_gen_array_elements) * 100 / - (rset_marked_pointers + rset_marked_array_elements); - PrintF(" total rset pointers %d, true cross generation ones %d (%%%d)\n", - (rset_marked_pointers + rset_marked_array_elements), - (cross_gen_pointers + cross_gen_array_elements), - pct); - ClearHistograms(); HeapObjectIterator obj_it(this); for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) CollectHistogramInfo(obj); ReportHistogram(true); } - - -// Dump the range of remembered set words between [start, end) corresponding -// to the pointers starting at object_p. The allocation_top is an object -// pointer which should not be read past. This is important for large object -// pages, where some bits in the remembered set range do not correspond to -// allocated addresses. -static void PrintRSetRange(Address start, Address end, Object** object_p, - Address allocation_top) { - Address rset_address = start; - - // If the range starts on on odd numbered word (eg, for large object extra - // remembered set ranges), print some spaces. - if ((reinterpret_cast<uintptr_t>(start) / kIntSize) % 2 == 1) { - PrintF(" "); - } - - // Loop over all the words in the range. - while (rset_address < end) { - uint32_t rset_word = Memory::uint32_at(rset_address); - int bit_position = 0; - - // Loop over all the bits in the word. - while (bit_position < kBitsPerInt) { - if (object_p == reinterpret_cast<Object**>(allocation_top)) { - // Print a bar at the allocation pointer. - PrintF("|"); - } else if (object_p > reinterpret_cast<Object**>(allocation_top)) { - // Do not dereference object_p past the allocation pointer. - PrintF("#"); - } else if ((rset_word & (1 << bit_position)) == 0) { - // Print a dot for zero bits. - PrintF("."); - } else if (Heap::InNewSpace(*object_p)) { - // Print an X for one bits for pointers to new space. - PrintF("X"); - } else { - // Print a circle for one bits for pointers to old space. - PrintF("o"); - } - - // Print a space after every 8th bit except the last. - if (bit_position % 8 == 7 && bit_position != (kBitsPerInt - 1)) { - PrintF(" "); - } - - // Advance to next bit. - bit_position++; - object_p++; - } - - // Print a newline after every odd numbered word, otherwise a space. - if ((reinterpret_cast<uintptr_t>(rset_address) / kIntSize) % 2 == 1) { - PrintF("\n"); - } else { - PrintF(" "); - } - - // Advance to next remembered set word. - rset_address += kIntSize; - } -} - - -void PagedSpace::DoPrintRSet(const char* space_name) { - PageIterator it(this, PageIterator::PAGES_IN_USE); - while (it.has_next()) { - Page* p = it.next(); - PrintF("%s page 0x%x:\n", space_name, p); - PrintRSetRange(p->RSetStart(), p->RSetEnd(), - reinterpret_cast<Object**>(p->ObjectAreaStart()), - p->AllocationTop()); - PrintF("\n"); - } -} - - -void OldSpace::PrintRSet() { DoPrintRSet("old"); } #endif // ----------------------------------------------------------------------------- @@ -2499,6 +2372,7 @@ void FixedSpace::MCCommitRelocationInfo() { if (it.has_next()) { accounting_stats_.WasteBytes( static_cast<int>(page->ObjectAreaEnd() - page_top)); + page->SetAllocationWatermark(page_top); } } @@ -2528,7 +2402,19 @@ HeapObject* FixedSpace::SlowAllocateRaw(int size_in_bytes) { Object* result = free_list_.Allocate(); if (!result->IsFailure()) { accounting_stats_.AllocateBytes(size_in_bytes); - return HeapObject::cast(result); + HeapObject* obj = HeapObject::cast(result); + Page* p = Page::FromAddress(obj->address()); + + if (obj->address() >= p->AllocationWatermark()) { + // There should be no hole between the allocation watermark + // and allocated object address. + // Memory above the allocation watermark was not swept and + // might contain garbage pointers to new space. + ASSERT(obj->address() == p->AllocationWatermark()); + p->SetAllocationWatermark(obj->address() + size_in_bytes); + } + + return obj; } } @@ -2558,8 +2444,11 @@ HeapObject* FixedSpace::AllocateInNextPage(Page* current_page, ASSERT(current_page->next_page()->is_valid()); ASSERT(allocation_info_.top == PageAllocationLimit(current_page)); ASSERT_EQ(object_size_in_bytes_, size_in_bytes); + Page* next_page = current_page->next_page(); + next_page->ClearGCFields(); + current_page->SetAllocationWatermark(allocation_info_.top); accounting_stats_.WasteBytes(page_extra_); - SetAllocationInfo(&allocation_info_, current_page->next_page()); + SetAllocationInfo(&allocation_info_, next_page); return AllocateLinearly(&allocation_info_, size_in_bytes); } @@ -2570,51 +2459,12 @@ void FixedSpace::ReportStatistics() { PrintF(" capacity: %d, waste: %d, available: %d, %%%d\n", Capacity(), Waste(), Available(), pct); - // Report remembered set statistics. - int rset_marked_pointers = 0; - int cross_gen_pointers = 0; - - PageIterator page_it(this, PageIterator::PAGES_IN_USE); - while (page_it.has_next()) { - Page* p = page_it.next(); - - for (Address rset_addr = p->RSetStart(); - rset_addr < p->RSetEnd(); - rset_addr += kIntSize) { - int rset = Memory::int_at(rset_addr); - if (rset != 0) { - // Bits were set - int intoff = - static_cast<int>(rset_addr - p->address() - Page::kRSetOffset); - int bitoff = 0; - for (; bitoff < kBitsPerInt; ++bitoff) { - if ((rset & (1 << bitoff)) != 0) { - int bitpos = intoff*kBitsPerByte + bitoff; - Address slot = p->OffsetToAddress(bitpos << kObjectAlignmentBits); - Object** obj = reinterpret_cast<Object**>(slot); - rset_marked_pointers++; - if (Heap::InNewSpace(*obj)) - cross_gen_pointers++; - } - } - } - } - } - - pct = rset_marked_pointers == 0 ? - 0 : cross_gen_pointers * 100 / rset_marked_pointers; - PrintF(" rset-marked pointers %d, to-new-space %d (%%%d)\n", - rset_marked_pointers, cross_gen_pointers, pct); - ClearHistograms(); HeapObjectIterator obj_it(this); for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) CollectHistogramInfo(obj); ReportHistogram(false); } - - -void FixedSpace::PrintRSet() { DoPrintRSet(name_); } #endif @@ -2793,8 +2643,7 @@ Object* LargeObjectSpace::AllocateRawInternal(int requested_size, chunk->set_size(chunk_size); first_chunk_ = chunk; - // Set the object address and size in the page header and clear its - // remembered set. + // Initialize page header. Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize)); Address object_address = page->ObjectAreaStart(); // Clear the low order bit of the second word in the page to flag it as a @@ -2802,13 +2651,7 @@ Object* LargeObjectSpace::AllocateRawInternal(int requested_size, // low order bit should already be clear. ASSERT((chunk_size & 0x1) == 0); page->SetIsLargeObjectPage(true); - page->ClearRSet(); - int extra_bytes = requested_size - object_size; - if (extra_bytes > 0) { - // The extra memory for the remembered set should be cleared. - memset(object_address + object_size, 0, extra_bytes); - } - + page->SetRegionMarks(Page::kAllRegionsCleanMarks); return HeapObject::FromAddress(object_address); } @@ -2823,8 +2666,7 @@ Object* LargeObjectSpace::AllocateRawCode(int size_in_bytes) { Object* LargeObjectSpace::AllocateRawFixedArray(int size_in_bytes) { ASSERT(0 < size_in_bytes); - int extra_rset_bytes = ExtraRSetBytesFor(size_in_bytes); - return AllocateRawInternal(size_in_bytes + extra_rset_bytes, + return AllocateRawInternal(size_in_bytes, size_in_bytes, NOT_EXECUTABLE); } @@ -2851,59 +2693,61 @@ Object* LargeObjectSpace::FindObject(Address a) { return Failure::Exception(); } - -void LargeObjectSpace::ClearRSet() { - ASSERT(Page::is_rset_in_use()); - - LargeObjectIterator it(this); - for (HeapObject* object = it.next(); object != NULL; object = it.next()) { - // We only have code, sequential strings, or fixed arrays in large - // object space, and only fixed arrays need remembered set support. - if (object->IsFixedArray()) { - // Clear the normal remembered set region of the page; - Page* page = Page::FromAddress(object->address()); - page->ClearRSet(); - - // Clear the extra remembered set. - int size = object->Size(); - int extra_rset_bytes = ExtraRSetBytesFor(size); - memset(object->address() + size, 0, extra_rset_bytes); - } - } -} - - -void LargeObjectSpace::IterateRSet(ObjectSlotCallback copy_object_func) { - ASSERT(Page::is_rset_in_use()); - - static void* lo_rset_histogram = StatsTable::CreateHistogram( - "V8.RSetLO", - 0, - // Keeping this histogram's buckets the same as the paged space histogram. - Page::kObjectAreaSize / kPointerSize, - 30); - +void LargeObjectSpace::IterateDirtyRegions(ObjectSlotCallback copy_object) { LargeObjectIterator it(this); for (HeapObject* object = it.next(); object != NULL; object = it.next()) { // We only have code, sequential strings, or fixed arrays in large // object space, and only fixed arrays can possibly contain pointers to // the young generation. if (object->IsFixedArray()) { - // Iterate the normal page remembered set range. Page* page = Page::FromAddress(object->address()); - Address object_end = object->address() + object->Size(); - int count = Heap::IterateRSetRange(page->ObjectAreaStart(), - Min(page->ObjectAreaEnd(), object_end), - page->RSetStart(), - copy_object_func); - - // Iterate the extra array elements. - if (object_end > page->ObjectAreaEnd()) { - count += Heap::IterateRSetRange(page->ObjectAreaEnd(), object_end, - object_end, copy_object_func); - } - if (lo_rset_histogram != NULL) { - StatsTable::AddHistogramSample(lo_rset_histogram, count); + uint32_t marks = page->GetRegionMarks(); + uint32_t newmarks = Page::kAllRegionsCleanMarks; + + if (marks != Page::kAllRegionsCleanMarks) { + // For a large page a single dirty mark corresponds to several + // regions (modulo 32). So we treat a large page as a sequence of + // normal pages of size Page::kPageSize having same dirty marks + // and subsequently iterate dirty regions on each of these pages. + Address start = object->address(); + Address end = page->ObjectAreaEnd(); + Address object_end = start + object->Size(); + + // Iterate regions of the first normal page covering object. + uint32_t first_region_number = page->GetRegionNumberForAddress(start); + newmarks |= + Heap::IterateDirtyRegions(marks >> first_region_number, + start, + end, + &Heap::IteratePointersInDirtyRegion, + copy_object) << first_region_number; + + start = end; + end = start + Page::kPageSize; + while (end <= object_end) { + // Iterate next 32 regions. + newmarks |= + Heap::IterateDirtyRegions(marks, + start, + end, + &Heap::IteratePointersInDirtyRegion, + copy_object); + start = end; + end = start + Page::kPageSize; + } + + if (start != object_end) { + // Iterate the last piece of an object which is less than + // Page::kPageSize. + newmarks |= + Heap::IterateDirtyRegions(marks, + start, + object_end, + &Heap::IteratePointersInDirtyRegion, + copy_object); + } + + page->SetRegionMarks(newmarks); } } } @@ -2995,7 +2839,7 @@ void LargeObjectSpace::Verify() { } else if (object->IsFixedArray()) { // We loop over fixed arrays ourselves, rather then using the visitor, // because the visitor doesn't support the start/offset iteration - // needed for IsRSetSet. + // needed for IsRegionDirty. FixedArray* array = FixedArray::cast(object); for (int j = 0; j < array->length(); j++) { Object* element = array->get(j); @@ -3004,8 +2848,11 @@ void LargeObjectSpace::Verify() { ASSERT(Heap::Contains(element_object)); ASSERT(element_object->map()->IsMap()); if (Heap::InNewSpace(element_object)) { - ASSERT(Page::IsRSetSet(object->address(), - FixedArray::kHeaderSize + j * kPointerSize)); + Address array_addr = object->address(); + Address element_addr = array_addr + FixedArray::kHeaderSize + + j * kPointerSize; + + ASSERT(Page::FromAddress(array_addr)->IsRegionDirty(element_addr)); } } } @@ -3046,33 +2893,6 @@ void LargeObjectSpace::CollectCodeStatistics() { } } } - - -void LargeObjectSpace::PrintRSet() { - LargeObjectIterator it(this); - for (HeapObject* object = it.next(); object != NULL; object = it.next()) { - if (object->IsFixedArray()) { - Page* page = Page::FromAddress(object->address()); - - Address allocation_top = object->address() + object->Size(); - PrintF("large page 0x%x:\n", page); - PrintRSetRange(page->RSetStart(), page->RSetEnd(), - reinterpret_cast<Object**>(object->address()), - allocation_top); - int extra_array_bytes = object->Size() - Page::kObjectAreaSize; - int extra_rset_bits = RoundUp(extra_array_bytes / kPointerSize, - kBitsPerInt); - PrintF("------------------------------------------------------------" - "-----------\n"); - PrintRSetRange(allocation_top, - allocation_top + extra_rset_bits / kBitsPerByte, - reinterpret_cast<Object**>(object->address() - + Page::kObjectAreaSize), - allocation_top); - PrintF("\n"); - } - } -} #endif // DEBUG } } // namespace v8::internal |