Commit 7d3f9f13 authored by ahaas's avatar ahaas Committed by Commit bot

[heap] Pass a force_promotion flag to the evacuation routine in the scavenger.

The {force_promotion} flag causes the scavenger to move an object to the
old generation instead of to the other semi-space. We use the flag to force
the promotion of objects which are referenced by code objects.

R=ulan@chromium.org

Committed: https://crrev.com/f2a7ba6449406d0b11a245aa1f5b4981265b6f20
Cr-Commit-Position: refs/heads/master@{#36443}

Review-Url: https://codereview.chromium.org/2002013002
Cr-Commit-Position: refs/heads/master@{#36462}
parent d2dff032
...@@ -1670,15 +1670,18 @@ void Heap::Scavenge() { ...@@ -1670,15 +1670,18 @@ void Heap::Scavenge() {
// Copy objects reachable from the old generation. // Copy objects reachable from the old generation.
TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS);
RememberedSet<OLD_TO_NEW>::Iterate(this, [this](Address addr) { RememberedSet<OLD_TO_NEW>::Iterate(this, [this](Address addr) {
return Scavenger::CheckAndScavengeObject(this, addr); return Scavenger::CheckAndScavengeObject(this, addr, DEFAULT_PROMOTION);
}); });
RememberedSet<OLD_TO_NEW>::IterateTyped( RememberedSet<OLD_TO_NEW>::IterateTyped(
this, [this](SlotType type, Address addr) { this, [this](SlotType type, Address addr) {
return UpdateTypedSlotHelper::UpdateTypedSlot( return UpdateTypedSlotHelper::UpdateTypedSlot(
isolate(), type, addr, [this](Object** addr) { isolate(), type, addr, [this](Object** addr) {
// We expect that objects referenced by code are long living.
// If we do not force promotion, then we need to clear
// old_to_new slots in dead code objects after mark-compact.
return Scavenger::CheckAndScavengeObject( return Scavenger::CheckAndScavengeObject(
this, reinterpret_cast<Address>(addr)); this, reinterpret_cast<Address>(addr), FORCE_PROMOTION);
}); });
}); });
} }
...@@ -4666,8 +4669,8 @@ void Heap::IteratePromotedObjectPointers(HeapObject* object, Address start, ...@@ -4666,8 +4669,8 @@ void Heap::IteratePromotedObjectPointers(HeapObject* object, Address start,
Object* target = *slot; Object* target = *slot;
if (target->IsHeapObject()) { if (target->IsHeapObject()) {
if (Heap::InFromSpace(target)) { if (Heap::InFromSpace(target)) {
callback(reinterpret_cast<HeapObject**>(slot), callback(reinterpret_cast<HeapObject**>(slot), HeapObject::cast(target),
HeapObject::cast(target)); DEFAULT_PROMOTION);
Object* new_target = *slot; Object* new_target = *slot;
if (InNewSpace(new_target)) { if (InNewSpace(new_target)) {
SLOW_DCHECK(Heap::InToSpace(new_target)); SLOW_DCHECK(Heap::InToSpace(new_target));
......
...@@ -301,7 +301,10 @@ class Scavenger; ...@@ -301,7 +301,10 @@ class Scavenger;
class ScavengeJob; class ScavengeJob;
class WeakObjectRetainer; class WeakObjectRetainer;
typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to); enum PromotionMode { FORCE_PROMOTION, DEFAULT_PROMOTION };
typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to,
PromotionMode mode);
// A queue of objects promoted during scavenge. Each object is accompanied // A queue of objects promoted during scavenge. Each object is accompanied
// by it's size to avoid dereferencing a map pointer for scanning. // by it's size to avoid dereferencing a map pointer for scanning.
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
void Scavenger::ScavengeObject(HeapObject** p, HeapObject* object) { void Scavenger::ScavengeObject(HeapObject** p, HeapObject* object,
PromotionMode promotion_mode) {
DCHECK(object->GetIsolate()->heap()->InFromSpace(object)); DCHECK(object->GetIsolate()->heap()->InFromSpace(object));
// We use the first word (where the map pointer usually is) of a heap // We use the first word (where the map pointer usually is) of a heap
...@@ -34,18 +35,19 @@ void Scavenger::ScavengeObject(HeapObject** p, HeapObject* object) { ...@@ -34,18 +35,19 @@ void Scavenger::ScavengeObject(HeapObject** p, HeapObject* object) {
// AllocationMementos are unrooted and shouldn't survive a scavenge // AllocationMementos are unrooted and shouldn't survive a scavenge
DCHECK(object->map() != object->GetHeap()->allocation_memento_map()); DCHECK(object->map() != object->GetHeap()->allocation_memento_map());
// Call the slow part of scavenge object. // Call the slow part of scavenge object.
return ScavengeObjectSlow(p, object); return ScavengeObjectSlow(p, object, promotion_mode);
} }
SlotCallbackResult Scavenger::CheckAndScavengeObject(Heap* heap, SlotCallbackResult Scavenger::CheckAndScavengeObject(
Address slot_address) { Heap* heap, Address slot_address, PromotionMode promotion_mode) {
Object** slot = reinterpret_cast<Object**>(slot_address); Object** slot = reinterpret_cast<Object**>(slot_address);
Object* object = *slot; Object* object = *slot;
if (heap->InFromSpace(object)) { if (heap->InFromSpace(object)) {
HeapObject* heap_object = reinterpret_cast<HeapObject*>(object); HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
DCHECK(heap_object->IsHeapObject()); DCHECK(heap_object->IsHeapObject());
ScavengeObject(reinterpret_cast<HeapObject**>(slot), heap_object); ScavengeObject(reinterpret_cast<HeapObject**>(slot), heap_object,
promotion_mode);
object = *slot; object = *slot;
// If the object was in from space before and is after executing the // If the object was in from space before and is after executing the
...@@ -67,7 +69,8 @@ void StaticScavengeVisitor::VisitPointer(Heap* heap, HeapObject* obj, ...@@ -67,7 +69,8 @@ void StaticScavengeVisitor::VisitPointer(Heap* heap, HeapObject* obj,
Object* object = *p; Object* object = *p;
if (!heap->InNewSpace(object)) return; if (!heap->InNewSpace(object)) return;
Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p), Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p),
reinterpret_cast<HeapObject*>(object)); reinterpret_cast<HeapObject*>(object),
DEFAULT_PROMOTION);
} }
} // namespace internal } // namespace internal
......
...@@ -200,15 +200,16 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -200,15 +200,16 @@ class ScavengingVisitor : public StaticVisitorBase {
return false; return false;
} }
template <ObjectContents object_contents, AllocationAlignment alignment> template <ObjectContents object_contents, AllocationAlignment alignment>
static inline void EvacuateObject(Map* map, HeapObject** slot, static inline void EvacuateObject(Map* map, HeapObject** slot,
HeapObject* object, int object_size) { HeapObject* object, int object_size,
PromotionMode promotion_mode) {
SLOW_DCHECK(object_size <= Page::kAllocatableMemory); SLOW_DCHECK(object_size <= Page::kAllocatableMemory);
SLOW_DCHECK(object->Size() == object_size); SLOW_DCHECK(object->Size() == object_size);
Heap* heap = map->GetHeap(); Heap* heap = map->GetHeap();
if (!heap->ShouldBePromoted(object->address(), object_size)) { if (promotion_mode != FORCE_PROMOTION &&
!heap->ShouldBePromoted(object->address(), object_size)) {
// A semi-space copy may fail due to fragmentation. In that case, we // A semi-space copy may fail due to fragmentation. In that case, we
// try to promote the object. // try to promote the object.
if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) {
...@@ -220,17 +221,20 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -220,17 +221,20 @@ class ScavengingVisitor : public StaticVisitorBase {
object_size)) { object_size)) {
return; return;
} }
if (promotion_mode == FORCE_PROMOTION) {
FatalProcessOutOfMemory("Scavenger: forced promotion\n");
}
// If promotion failed, we try to copy the object to the other semi-space // If promotion failed, we try to copy the object to the other semi-space
if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return; if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return;
FatalProcessOutOfMemory("Scavenger: semi-space copy\n"); FatalProcessOutOfMemory("Scavenger: semi-space copy\n");
} }
static inline void EvacuateJSFunction(Map* map, HeapObject** slot, static inline void EvacuateJSFunction(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object); PromotionMode promotion_mode) {
ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object,
promotion_mode);
if (marks_handling == IGNORE_MARKS) return; if (marks_handling == IGNORE_MARKS) return;
...@@ -252,43 +256,45 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -252,43 +256,45 @@ class ScavengingVisitor : public StaticVisitorBase {
} }
} }
static inline void EvacuateFixedArray(Map* map, HeapObject** slot, static inline void EvacuateFixedArray(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
PromotionMode promotion_mode) {
int length = reinterpret_cast<FixedArray*>(object)->synchronized_length(); int length = reinterpret_cast<FixedArray*>(object)->synchronized_length();
int object_size = FixedArray::SizeFor(length); int object_size = FixedArray::SizeFor(length);
EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, object_size,
object_size); promotion_mode);
} }
static inline void EvacuateFixedDoubleArray(Map* map, HeapObject** slot, static inline void EvacuateFixedDoubleArray(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
PromotionMode promotion_mode) {
int length = reinterpret_cast<FixedDoubleArray*>(object)->length(); int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
int object_size = FixedDoubleArray::SizeFor(length); int object_size = FixedDoubleArray::SizeFor(length);
EvacuateObject<DATA_OBJECT, kDoubleAligned>(map, slot, object, object_size); EvacuateObject<DATA_OBJECT, kDoubleAligned>(map, slot, object, object_size,
promotion_mode);
} }
static inline void EvacuateFixedTypedArray(Map* map, HeapObject** slot, static inline void EvacuateFixedTypedArray(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
PromotionMode promotion_mode) {
int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size(); int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size();
EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, object_size,
object_size); promotion_mode);
} }
static inline void EvacuateFixedFloat64Array(Map* map, HeapObject** slot, static inline void EvacuateFixedFloat64Array(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
PromotionMode promotion_mode) {
int object_size = reinterpret_cast<FixedFloat64Array*>(object)->size(); int object_size = reinterpret_cast<FixedFloat64Array*>(object)->size();
EvacuateObject<POINTER_OBJECT, kDoubleAligned>(map, slot, object, EvacuateObject<POINTER_OBJECT, kDoubleAligned>(map, slot, object,
object_size); object_size, promotion_mode);
} }
static inline void EvacuateJSArrayBuffer(Map* map, HeapObject** slot, static inline void EvacuateJSArrayBuffer(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object); PromotionMode promotion_mode) {
ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object,
promotion_mode);
Heap* heap = map->GetHeap(); Heap* heap = map->GetHeap();
MapWord map_word = object->map_word(); MapWord map_word = object->map_word();
...@@ -299,32 +305,35 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -299,32 +305,35 @@ class ScavengingVisitor : public StaticVisitorBase {
} }
} }
static inline void EvacuateByteArray(Map* map, HeapObject** slot, static inline void EvacuateByteArray(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
PromotionMode promotion_mode) {
int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize(); int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size,
promotion_mode);
} }
static inline void EvacuateSeqOneByteString(Map* map, HeapObject** slot, static inline void EvacuateSeqOneByteString(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
PromotionMode promotion_mode) {
int object_size = SeqOneByteString::cast(object) int object_size = SeqOneByteString::cast(object)
->SeqOneByteStringSize(map->instance_type()); ->SeqOneByteStringSize(map->instance_type());
EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size,
promotion_mode);
} }
static inline void EvacuateSeqTwoByteString(Map* map, HeapObject** slot, static inline void EvacuateSeqTwoByteString(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
PromotionMode promotion_mode) {
int object_size = SeqTwoByteString::cast(object) int object_size = SeqTwoByteString::cast(object)
->SeqTwoByteStringSize(map->instance_type()); ->SeqTwoByteStringSize(map->instance_type());
EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size,
promotion_mode);
} }
static inline void EvacuateShortcutCandidate(Map* map, HeapObject** slot, static inline void EvacuateShortcutCandidate(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
PromotionMode promotion_mode) {
DCHECK(IsShortcutCandidate(map->instance_type())); DCHECK(IsShortcutCandidate(map->instance_type()));
Heap* heap = map->GetHeap(); Heap* heap = map->GetHeap();
...@@ -350,14 +359,14 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -350,14 +359,14 @@ class ScavengingVisitor : public StaticVisitorBase {
return; return;
} }
Scavenger::ScavengeObjectSlow(slot, first); Scavenger::ScavengeObjectSlow(slot, first, promotion_mode);
object->set_map_word(MapWord::FromForwardingAddress(*slot)); object->set_map_word(MapWord::FromForwardingAddress(*slot));
return; return;
} }
int object_size = ConsString::kSize; int object_size = ConsString::kSize;
EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, object_size,
object_size); promotion_mode);
} }
template <ObjectContents object_contents> template <ObjectContents object_contents>
...@@ -365,15 +374,17 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -365,15 +374,17 @@ class ScavengingVisitor : public StaticVisitorBase {
public: public:
template <int object_size> template <int object_size>
static inline void VisitSpecialized(Map* map, HeapObject** slot, static inline void VisitSpecialized(Map* map, HeapObject** slot,
HeapObject* object) { HeapObject* object,
EvacuateObject<object_contents, kWordAligned>(map, slot, object, PromotionMode promotion_mode) {
object_size); EvacuateObject<object_contents, kWordAligned>(
map, slot, object, object_size, promotion_mode);
} }
static inline void Visit(Map* map, HeapObject** slot, HeapObject* object) { static inline void Visit(Map* map, HeapObject** slot, HeapObject* object,
PromotionMode promotion_mode) {
int object_size = map->instance_size(); int object_size = map->instance_size();
EvacuateObject<object_contents, kWordAligned>(map, slot, object, EvacuateObject<object_contents, kWordAligned>(
object_size); map, slot, object, object_size, promotion_mode);
} }
}; };
...@@ -399,13 +410,15 @@ void Scavenger::Initialize() { ...@@ -399,13 +410,15 @@ void Scavenger::Initialize() {
// static // static
void Scavenger::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { void Scavenger::ScavengeObjectSlow(HeapObject** p, HeapObject* object,
PromotionMode promotion_mode) {
SLOW_DCHECK(object->GetIsolate()->heap()->InFromSpace(object)); SLOW_DCHECK(object->GetIsolate()->heap()->InFromSpace(object));
MapWord first_word = object->map_word(); MapWord first_word = object->map_word();
SLOW_DCHECK(!first_word.IsForwardingAddress()); SLOW_DCHECK(!first_word.IsForwardingAddress());
Map* map = first_word.ToMap(); Map* map = first_word.ToMap();
Scavenger* scavenger = map->GetHeap()->scavenge_collector_; Scavenger* scavenger = map->GetHeap()->scavenge_collector_;
scavenger->scavenging_visitors_table_.GetVisitor(map)(map, p, object); scavenger->scavenging_visitors_table_.GetVisitor(map)(map, p, object,
promotion_mode);
} }
......
...@@ -12,7 +12,8 @@ namespace v8 { ...@@ -12,7 +12,8 @@ namespace v8 {
namespace internal { namespace internal {
typedef void (*ScavengingCallback)(Map* map, HeapObject** slot, typedef void (*ScavengingCallback)(Map* map, HeapObject** slot,
HeapObject* object); HeapObject* object,
PromotionMode promotion_mode);
class Scavenger { class Scavenger {
public: public:
...@@ -25,12 +26,15 @@ class Scavenger { ...@@ -25,12 +26,15 @@ class Scavenger {
// necessary, the object might be promoted to an old space. The caller must // necessary, the object might be promoted to an old space. The caller must
// ensure the precondition that the object is (a) a heap object and (b) in // ensure the precondition that the object is (a) a heap object and (b) in
// the heap's from space. // the heap's from space.
static inline void ScavengeObject(HeapObject** p, HeapObject* object); static inline void ScavengeObject(
static inline SlotCallbackResult CheckAndScavengeObject(Heap* heap, HeapObject** p, HeapObject* object,
Address slot_address); PromotionMode promotion_mode = DEFAULT_PROMOTION);
static inline SlotCallbackResult CheckAndScavengeObject(
Heap* heap, Address slot_address, PromotionMode promotion_mode);
// Slow part of {ScavengeObject} above. // Slow part of {ScavengeObject} above.
static void ScavengeObjectSlow(HeapObject** p, HeapObject* object); static void ScavengeObjectSlow(HeapObject** p, HeapObject* object,
PromotionMode promotion_mode);
// Chooses an appropriate static visitor table depending on the current state // Chooses an appropriate static visitor table depending on the current state
// of the heap (i.e. incremental marking, logging and profiling). // of the heap (i.e. incremental marking, logging and profiling).
......
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