Index: src/heap.cc |
diff --git a/src/heap.cc b/src/heap.cc |
index 4dea51050d3f1a37e21b81ae7ea9ec53ceb4d341..db13637c9aa9222c631d461ad227f45f727d43fe 100644 |
--- a/src/heap.cc |
+++ b/src/heap.cc |
@@ -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(); |
} |