Commit 559826f6 authored by hpayer@chromium.org's avatar hpayer@chromium.org

Make memento checks more stable. Add filler at the end of new space and check...

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
parent db7124dc
......@@ -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);
......
......@@ -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<int>(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");
......
......@@ -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<int>(limit - from_top);
heap()->CreateFillerObjectAt(from_top, remaining_in_page);
}
int survivors_size = 0;
// First pass: traverse all objects in inactive semispace, remove marks,
......
......@@ -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);
......
......@@ -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(); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment