Fix migration checks and extend them to the Scavenger.

R=hpayer@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16265 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e814a9b9
...@@ -439,6 +439,43 @@ AllocationSpace Heap::TargetSpaceId(InstanceType type) { ...@@ -439,6 +439,43 @@ AllocationSpace Heap::TargetSpaceId(InstanceType type) {
} }
bool Heap::AllowedToBeMigrated(HeapObject* object, AllocationSpace dst) {
// Object migration is governed by the following rules:
//
// 1) Objects in new-space can be migrated to one of the old spaces
// that matches their target space or they stay in new-space.
// 2) Objects in old-space stay in the same space when migrating.
// 3) Fillers (two or more words) can migrate due to left-trimming of
// fixed arrays in new-space, old-data-space and old-pointer-space.
// 4) Fillers (one word) can never migrate, they are skipped by
// incremental marking explicitly to prevent invalid pattern.
//
// Since this function is used for debugging only, we do not place
// asserts here, but check everything explicitly.
if (object->map() == one_pointer_filler_map()) return false;
InstanceType type = object->map()->instance_type();
MemoryChunk* chunk = MemoryChunk::FromAddress(object->address());
AllocationSpace src = chunk->owner()->identity();
switch (src) {
case NEW_SPACE:
return dst == src || dst == TargetSpaceId(type);
case OLD_POINTER_SPACE:
return dst == src && (dst == TargetSpaceId(type) || object->IsFiller());
case OLD_DATA_SPACE:
return dst == src && dst == TargetSpaceId(type);
case CODE_SPACE:
return dst == src && type == CODE_TYPE;
case MAP_SPACE:
case CELL_SPACE:
case PROPERTY_CELL_SPACE:
case LO_SPACE:
return false;
}
UNREACHABLE();
return false;
}
void Heap::CopyBlock(Address dst, Address src, int byte_size) { void Heap::CopyBlock(Address dst, Address src, int byte_size) {
CopyWords(reinterpret_cast<Object**>(dst), CopyWords(reinterpret_cast<Object**>(dst),
reinterpret_cast<Object**>(src), reinterpret_cast<Object**>(src),
......
...@@ -2088,10 +2088,13 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -2088,10 +2088,13 @@ class ScavengingVisitor : public StaticVisitorBase {
MaybeObject* maybe_result; MaybeObject* maybe_result;
if (object_contents == DATA_OBJECT) { if (object_contents == DATA_OBJECT) {
// TODO(mstarzinger): Turn this check into a regular assert soon!
CHECK(heap->AllowedToBeMigrated(object, OLD_DATA_SPACE));
maybe_result = heap->old_data_space()->AllocateRaw(allocation_size); maybe_result = heap->old_data_space()->AllocateRaw(allocation_size);
} else { } else {
maybe_result = // TODO(mstarzinger): Turn this check into a regular assert soon!
heap->old_pointer_space()->AllocateRaw(allocation_size); CHECK(heap->AllowedToBeMigrated(object, OLD_POINTER_SPACE));
maybe_result = heap->old_pointer_space()->AllocateRaw(allocation_size);
} }
Object* result = NULL; // Initialization to please compiler. Object* result = NULL; // Initialization to please compiler.
...@@ -2121,6 +2124,8 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -2121,6 +2124,8 @@ class ScavengingVisitor : public StaticVisitorBase {
return; return;
} }
} }
// TODO(mstarzinger): Turn this check into a regular assert soon!
CHECK(heap->AllowedToBeMigrated(object, NEW_SPACE));
MaybeObject* allocation = heap->new_space()->AllocateRaw(allocation_size); MaybeObject* allocation = heap->new_space()->AllocateRaw(allocation_size);
heap->promotion_queue()->SetNewLimit(heap->new_space()->top()); heap->promotion_queue()->SetNewLimit(heap->new_space()->top());
Object* result = allocation->ToObjectUnchecked(); Object* result = allocation->ToObjectUnchecked();
......
...@@ -1391,6 +1391,10 @@ class Heap { ...@@ -1391,6 +1391,10 @@ class Heap {
inline OldSpace* TargetSpace(HeapObject* object); inline OldSpace* TargetSpace(HeapObject* object);
static inline AllocationSpace TargetSpaceId(InstanceType type); static inline AllocationSpace TargetSpaceId(InstanceType type);
// Checks whether the given object is allowed to be migrated from it's
// current space into the given destination space. Used for debugging.
inline bool AllowedToBeMigrated(HeapObject* object, AllocationSpace dest);
// Sets the stub_cache_ (only used when expanding the dictionary). // Sets the stub_cache_ (only used when expanding the dictionary).
void public_set_code_stubs(UnseededNumberDictionary* value) { void public_set_code_stubs(UnseededNumberDictionary* value) {
roots_[kCodeStubsRootIndex] = value; roots_[kCodeStubsRootIndex] = value;
......
...@@ -2743,12 +2743,10 @@ void MarkCompactCollector::MigrateObject(Address dst, ...@@ -2743,12 +2743,10 @@ void MarkCompactCollector::MigrateObject(Address dst,
int size, int size,
AllocationSpace dest) { AllocationSpace dest) {
HEAP_PROFILE(heap(), ObjectMoveEvent(src, dst)); HEAP_PROFILE(heap(), ObjectMoveEvent(src, dst));
// TODO(hpayer): Replace that check with an assert. // TODO(hpayer): Replace these checks with asserts.
CHECK(heap()->AllowedToBeMigrated(HeapObject::FromAddress(src), dest));
CHECK(dest != LO_SPACE && size <= Page::kMaxNonCodeHeapObjectSize); CHECK(dest != LO_SPACE && size <= Page::kMaxNonCodeHeapObjectSize);
if (dest == OLD_POINTER_SPACE) { if (dest == OLD_POINTER_SPACE) {
// TODO(hpayer): Replace this check with an assert.
HeapObject* heap_object = HeapObject::FromAddress(src);
CHECK(heap_->TargetSpace(heap_object) == heap_->old_pointer_space());
Address src_slot = src; Address src_slot = src;
Address dst_slot = dst; Address dst_slot = dst;
ASSERT(IsAligned(size, kPointerSize)); ASSERT(IsAligned(size, kPointerSize));
...@@ -2794,13 +2792,6 @@ void MarkCompactCollector::MigrateObject(Address dst, ...@@ -2794,13 +2792,6 @@ void MarkCompactCollector::MigrateObject(Address dst,
Code::cast(HeapObject::FromAddress(dst))->Relocate(dst - src); Code::cast(HeapObject::FromAddress(dst))->Relocate(dst - src);
} else { } else {
ASSERT(dest == OLD_DATA_SPACE || dest == NEW_SPACE); ASSERT(dest == OLD_DATA_SPACE || dest == NEW_SPACE);
// Objects in old data space can just be moved by compaction to a different
// page in old data space.
// TODO(hpayer): Replace the following check with an assert.
CHECK(!heap_->old_data_space()->Contains(src) ||
(heap_->old_data_space()->Contains(dst) &&
heap_->TargetSpace(HeapObject::FromAddress(src)) ==
heap_->old_data_space()));
heap()->MoveBlock(dst, src, size); heap()->MoveBlock(dst, src, size);
} }
Memory::Address_at(src) = dst; Memory::Address_at(src) = dst;
......
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