Make memento checks more stable. Add filler at the end of new space and check if...
authorhpayer@chromium.org <hpayer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 3 Feb 2014 12:20:15 +0000 (12:20 +0000)
committerhpayer@chromium.org <hpayer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 3 Feb 2014 12:20:15 +0000 (12:20 +0000)
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
src/heap.cc
src/mark-compact.cc
src/objects.cc
src/spaces.h

index b1657ab9878dca4c5b1145bb06788e96ac4b9c25..f28b82c732a71088b46dcb9e93f4e85c470ec78f 100644 (file)
@@ -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);
index f8588b87e6eda4763e3f757a8deda15fa47fbd42..a6db39c58cde422c7536d22c2dab95a232a75f9e 100644 (file)
@@ -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");
index fc9f16627e423910358d2cbdec0707f3fd44fe9f..81de035b0af7a6ae67de51f738b30ecbdbcb2da5 100644 (file)
@@ -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,
index 7c67539d7b6172ad9120676481c6292f3dfd5923..8bcfcd946a0ccf4dcfd830b1b2075996dad1e0b4 100644 (file)
@@ -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);
index 9d299c64841e9256af6ebd0cb5e9811778e8249c..9d47f81ac63dbbf65d357769c02f6307bf6ff15f 100644 (file)
@@ -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(); }