From 559826f649a0c13f0e83e3f49ccf199ed5c68372 Mon Sep 17 00:00:00 2001 From: "hpayer@chromium.org" Date: Mon, 3 Feb 2014 12:20:15 +0000 Subject: [PATCH] Make memento checks more stable. Add filler at the end of new space and check if object and memento are on the same new space page. BUG= R=bmeurer@chromium.org, mvstanton@chromium.org Review URL: https://codereview.chromium.org/152613002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19024 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap-inl.h | 24 +++++++++++++++--------- src/heap.cc | 12 ++++++++++++ src/mark-compact.cc | 14 -------------- src/objects.cc | 19 +++++++++++++++---- src/spaces.h | 12 ++++++++++++ 5 files changed, 54 insertions(+), 27 deletions(-) diff --git a/src/heap-inl.h b/src/heap-inl.h index b1657ab..f28b82c 100644 --- a/src/heap-inl.h +++ b/src/heap-inl.h @@ -493,15 +493,21 @@ void Heap::UpdateAllocationSiteFeedback(HeapObject* object) { if (!FLAG_allocation_site_pretenuring || !AllocationSite::CanTrack(object->map()->instance_type())) return; - // Either object is the last object in the from space, or there is another - // object of at least word size (the header map word) following it, so - // suffices to compare ptr and top here. - Address ptr = object->address() + object->Size(); - Address top = heap->new_space()->FromSpacePageHigh(); - ASSERT(ptr == top || ptr + HeapObject::kHeaderSize <= top); - if (ptr == top) return; - - HeapObject* candidate = HeapObject::FromAddress(ptr); + // Check if there is potentially a memento behind the object. If + // the last word of the momento is on another page we return + // immediatelly. Note that we do not have to compare with the current + // top pointer of the from space page, since we always install filler + // objects above the top pointer of a from space page when performing + // a garbage collection. + Address object_address = object->address(); + Address memento_address = object_address + object->Size(); + Address last_memento_word_address = memento_address + kPointerSize; + if (!NewSpacePage::OnSamePage(object_address, + last_memento_word_address)) { + return; + } + + HeapObject* candidate = HeapObject::FromAddress(memento_address); if (candidate->map() != heap->allocation_memento_map()) return; AllocationMemento* memento = AllocationMemento::cast(candidate); diff --git a/src/heap.cc b/src/heap.cc index f8588b8..a6db39c 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -768,6 +768,18 @@ bool Heap::CollectGarbage(AllocationSpace space, allocation_timeout_ = Max(6, FLAG_gc_interval); #endif + // There may be an allocation memento behind every object in new space. + // If we evacuate a not full new space or if we are on the last page of + // the new space, then there may be uninitialized memory behind the top + // pointer of the new space page. We store a filler object there to + // identify the unused space. + Address from_top = new_space_.top(); + Address from_limit = new_space_.limit(); + if (from_top < from_limit) { + int remaining_in_page = static_cast(from_limit - from_top); + CreateFillerObjectAt(from_top, remaining_in_page); + } + if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { if (FLAG_trace_incremental_marking) { PrintF("[IncrementalMarking] Scavenge during marking.\n"); diff --git a/src/mark-compact.cc b/src/mark-compact.cc index fc9f166..81de035 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -3007,20 +3007,6 @@ void MarkCompactCollector::EvacuateNewSpace() { new_space->Flip(); new_space->ResetAllocationInfo(); - // UpdateAllocationSiteFeedback expects that only objects at the end of - // newspace are not guaranteed to have the next word clear. It relies on - // FromSpacePageHigh to check whether an object is at the end of newspace. - // However, it is possible that newspace is being evacuated without it being - // full, e.g. to make the heap iterable, hence top will not equal high. In - // that case, fill up newspace with a filler to ensure the next word is - // cleared. - if (FLAG_allocation_site_pretenuring && - from_top < new_space->FromSpacePageHigh()) { - Address limit = NewSpacePage::FromLimit(from_top)->area_end(); - int remaining_in_page = static_cast(limit - from_top); - heap()->CreateFillerObjectAt(from_top, remaining_in_page); - } - int survivors_size = 0; // First pass: traverse all objects in inactive semispace, remove marks, diff --git a/src/objects.cc b/src/objects.cc index 7c67539..8bcfcd9 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -12838,15 +12838,26 @@ MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { Heap* heap = GetHeap(); if (!heap->InNewSpace(this)) return this; + // Check if there is potentially a memento behind the object. If + // the last word of the momento is on another page we return + // immediatelly. + Address object_address = address(); + Address memento_address = object_address + JSArray::kSize; + Address last_memento_word_address = memento_address + kPointerSize; + if (!NewSpacePage::OnSamePage(object_address, + last_memento_word_address)) { + return this; + } + // Either object is the last object in the new space, or there is another // object of at least word size (the header map word) following it, so // suffices to compare ptr and top here. - Address ptr = address() + JSArray::kSize; Address top = heap->NewSpaceTop(); - ASSERT(ptr == top || ptr + HeapObject::kHeaderSize <= top); - if (ptr == top) return this; + ASSERT(memento_address == top || + memento_address + HeapObject::kHeaderSize <= top); + if (memento_address == top) return this; - HeapObject* candidate = HeapObject::FromAddress(ptr); + HeapObject* candidate = HeapObject::FromAddress(memento_address); if (candidate->map() != heap->allocation_memento_map()) return this; AllocationMemento* memento = AllocationMemento::cast(candidate); diff --git a/src/spaces.h b/src/spaces.h index 9d299c6..9d47f81 100644 --- a/src/spaces.h +++ b/src/spaces.h @@ -2061,6 +2061,12 @@ class NewSpacePage : public MemoryChunk { return NewSpacePage::FromAddress(address_limit - 1); } + // Checks if address1 and address2 are on the same new space page. + static inline bool OnSamePage(Address address1, Address address2) { + return NewSpacePage::FromAddress(address1) == + NewSpacePage::FromAddress(address2); + } + private: // Create a NewSpacePage object that is only used as anchor // for the doubly-linked list of real pages. @@ -2455,6 +2461,12 @@ class NewSpace : public Space { allocation_info_.set_top(top); } + // Return the address of the allocation pointer limit in the active semispace. + Address limit() { + ASSERT(to_space_.current_page()->ContainsLimit(allocation_info_.limit())); + return allocation_info_.limit(); + } + // Return the address of the first object in the active semispace. Address bottom() { return to_space_.space_start(); } -- 2.7.4