Promotion is the backup strategy when semi-space copy fails and vice versa.
authorhpayer@chromium.org <hpayer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 25 Jun 2014 09:31:25 +0000 (09:31 +0000)
committerhpayer@chromium.org <hpayer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 25 Jun 2014 09:31:25 +0000 (09:31 +0000)
BUG=
R=ishell@chromium.org

Review URL: https://codereview.chromium.org/356613004

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22002 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/heap-inl.h
src/heap.cc
src/heap.h

index 22e4c97..162dac2 100644 (file)
@@ -388,8 +388,6 @@ bool Heap::OldGenerationAllocationLimitReached() {
 
 
 bool Heap::ShouldBePromoted(Address old_address, int object_size) {
-  // An object should be promoted if the object has survived a
-  // scavenge operation.
   NewSpacePage* page = NewSpacePage::FromAddress(old_address);
   Address age_mark = new_space_.age_mark();
   return page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK) &&
index 4dea510..db13637 100644 (file)
@@ -1970,14 +1970,49 @@ class ScavengingVisitor : public StaticVisitorBase {
     }
   }
 
+  template<int alignment>
+  static inline bool SemiSpaceCopyObject(Map* map,
+                                         HeapObject** slot,
+                                         HeapObject* object,
+                                         int object_size) {
+    Heap* heap = map->GetHeap();
+
+    int allocation_size = object_size;
+    if (alignment != kObjectAlignment) {
+      ASSERT(alignment == kDoubleAlignment);
+      allocation_size += kPointerSize;
+    }
+
+    ASSERT(heap->AllowedToBeMigrated(object, NEW_SPACE));
+    AllocationResult allocation =
+        heap->new_space()->AllocateRaw(allocation_size);
+
+    HeapObject* target = NULL;  // Initialization to please compiler.
+    if (allocation.To(&target)) {
+      if (alignment != kObjectAlignment) {
+        target = EnsureDoubleAligned(heap, target, allocation_size);
+      }
+
+      // Order is important: slot might be inside of the target if target
+      // was allocated over a dead object and slot comes from the store
+      // buffer.
+      *slot = target;
+      MigrateObject(heap, object, target, object_size);
+
+      heap->promotion_queue()->SetNewLimit(heap->new_space()->top());
+      heap->IncrementSemiSpaceCopiedObjectSize(object_size);
+      return true;
+    }
+    return false;
+  }
+
 
   template<ObjectContents object_contents, int alignment>
-  static inline void EvacuateObject(Map* map,
-                                    HeapObject** slot,
-                                    HeapObject* object,
-                                    int object_size) {
-    SLOW_ASSERT(object_size <= Page::kMaxRegularHeapObjectSize);
-    SLOW_ASSERT(object->Size() == object_size);
+  static inline bool PromoteObject(Map* map,
+                                   HeapObject** slot,
+                                   HeapObject* object,
+                                   int object_size) {
+    Heap* heap = map->GetHeap();
 
     int allocation_size = object_size;
     if (alignment != kObjectAlignment) {
@@ -1985,73 +2020,68 @@ class ScavengingVisitor : public StaticVisitorBase {
       allocation_size += kPointerSize;
     }
 
-    Heap* heap = map->GetHeap();
-    if (heap->ShouldBePromoted(object->address(), object_size)) {
-      AllocationResult allocation;
+    AllocationResult allocation;
+    if (object_contents == DATA_OBJECT) {
+      ASSERT(heap->AllowedToBeMigrated(object, OLD_DATA_SPACE));
+      allocation = heap->old_data_space()->AllocateRaw(allocation_size);
+    } else {
+      ASSERT(heap->AllowedToBeMigrated(object, OLD_POINTER_SPACE));
+      allocation = heap->old_pointer_space()->AllocateRaw(allocation_size);
+    }
 
-      if (object_contents == DATA_OBJECT) {
-        ASSERT(heap->AllowedToBeMigrated(object, OLD_DATA_SPACE));
-        allocation = heap->old_data_space()->AllocateRaw(allocation_size);
-      } else {
-        ASSERT(heap->AllowedToBeMigrated(object, OLD_POINTER_SPACE));
-        allocation = heap->old_pointer_space()->AllocateRaw(allocation_size);
+    HeapObject* target = NULL;  // Initialization to please compiler.
+    if (allocation.To(&target)) {
+      if (alignment != kObjectAlignment) {
+        target = EnsureDoubleAligned(heap, target, allocation_size);
       }
 
-      HeapObject* target = NULL;  // Initialization to please compiler.
-      if (allocation.To(&target)) {
-        if (alignment != kObjectAlignment) {
-          target = EnsureDoubleAligned(heap, target, allocation_size);
+      // Order is important: slot might be inside of the target if target
+      // was allocated over a dead object and slot comes from the store
+      // buffer.
+      *slot = target;
+      MigrateObject(heap, object, target, object_size);
+
+      if (object_contents == POINTER_OBJECT) {
+        if (map->instance_type() == JS_FUNCTION_TYPE) {
+          heap->promotion_queue()->insert(
+              target, JSFunction::kNonWeakFieldsEndOffset);
+        } else {
+          heap->promotion_queue()->insert(target, object_size);
         }
+      }
+      heap->IncrementPromotedObjectsSize(object_size);
+      return true;
+    }
+    return false;
+  }
 
-        // Order is important: slot might be inside of the target if target
-        // was allocated over a dead object and slot comes from the store
-        // buffer.
-        *slot = target;
-        MigrateObject(heap, object, target, object_size);
 
-        if (object_contents == POINTER_OBJECT) {
-          if (map->instance_type() == JS_FUNCTION_TYPE) {
-            heap->promotion_queue()->insert(
-                target, JSFunction::kNonWeakFieldsEndOffset);
-          } else {
-            heap->promotion_queue()->insert(target, object_size);
-          }
-        }
+  template<ObjectContents object_contents, int alignment>
+  static inline void EvacuateObject(Map* map,
+                                    HeapObject** slot,
+                                    HeapObject* object,
+                                    int object_size) {
+    SLOW_ASSERT(object_size <= Page::kMaxRegularHeapObjectSize);
+    SLOW_ASSERT(object->Size() == object_size);
+    Heap* heap = map->GetHeap();
 
-        heap->IncrementPromotedObjectsSize(object_size);
+    if (!heap->ShouldBePromoted(object->address(), object_size)) {
+      // A semi-space copy may fail due to fragmentation. In that case, we
+      // try to promote the object.
+      if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) {
         return;
       }
     }
-    ASSERT(heap->AllowedToBeMigrated(object, NEW_SPACE));
-    AllocationResult allocation =
-        heap->new_space()->AllocateRaw(allocation_size);
-    heap->promotion_queue()->SetNewLimit(heap->new_space()->top());
-
-    // Allocation in the other semi-space may fail due to fragmentation.
-    // In that case we allocate in the old generation.
-    if (allocation.IsRetry()) {
-      if (object_contents == DATA_OBJECT) {
-        ASSERT(heap->AllowedToBeMigrated(object, OLD_DATA_SPACE));
-        allocation = heap->old_data_space()->AllocateRaw(allocation_size);
-      } else {
-        ASSERT(heap->AllowedToBeMigrated(object, OLD_POINTER_SPACE));
-        allocation = heap->old_pointer_space()->AllocateRaw(allocation_size);
-      }
-    }
-
-    HeapObject* target = HeapObject::cast(allocation.ToObjectChecked());
 
-    if (alignment != kObjectAlignment) {
-      target = EnsureDoubleAligned(heap, target, allocation_size);
+    if (PromoteObject<object_contents, alignment>(
+        map, slot, object, object_size)) {
+      return;
     }
 
-    // Order is important: slot might be inside of the target if target
-    // was allocated over a dead object and slot comes from the store
-    // buffer.
-    *slot = target;
-    MigrateObject(heap, object, target, object_size);
-    heap->IncrementSemiSpaceCopiedObjectSize(object_size);
-    return;
+    // If promotion failed, we try to copy the object to the other semi-space
+    if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return;
+
+    UNREACHABLE();
   }
 
 
index cb438b1..fa711f2 100644 (file)
@@ -1200,10 +1200,8 @@ class Heap {
 
   void VisitExternalResources(v8::ExternalResourceVisitor* visitor);
 
-  // Helper function that governs the promotion policy from new space to
-  // old.  If the object's old address lies below the new space's age
-  // mark or if we've already filled the bottom 1/16th of the to space,
-  // we try to promote this object.
+  // An object should be promoted if the object has survived a
+  // scavenge operation.
   inline bool ShouldBePromoted(Address old_address, int object_size);
 
   void ClearJSFunctionResultCaches();