Reverting r4318 (merge of scavenge into sweeping pass of MSC garbage collector)

Review URL: http://codereview.chromium.org/1622016

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4370 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vegorov@chromium.org 2010-04-09 08:16:25 +00:00
parent 88be99e9c0
commit 82ddab5fd5
6 changed files with 150 additions and 403 deletions

View File

@ -240,27 +240,6 @@ void Heap::CopyBlock(Object** dst, Object** src, int byte_size) {
} }
void Heap::MoveBlock(Object** dst, Object** src, size_t byte_size) {
ASSERT(IsAligned<size_t>(byte_size, kPointerSize));
int size_in_words = byte_size / kPointerSize;
if ((dst < src) || (dst >= (src + size_in_words))) {
ASSERT((dst >= (src + size_in_words)) ||
((OffsetFrom(reinterpret_cast<Address>(src)) -
OffsetFrom(reinterpret_cast<Address>(dst))) >= kPointerSize));
Object** end = src + size_in_words;
while (src != end) {
*dst++ = *src++;
}
} else {
memmove(dst, src, byte_size);
}
}
void Heap::ScavengeObject(HeapObject** p, HeapObject* object) { void Heap::ScavengeObject(HeapObject** p, HeapObject* object) {
ASSERT(InFromSpace(object)); ASSERT(InFromSpace(object));

View File

@ -562,18 +562,23 @@ void Heap::PerformGarbageCollection(AllocationSpace space,
EnsureFromSpaceIsCommitted(); EnsureFromSpaceIsCommitted();
// Perform mark-sweep with optional compaction.
if (collector == MARK_COMPACTOR) { if (collector == MARK_COMPACTOR) {
// Perform mark-sweep with optional compaction.
MarkCompact(tracer); MarkCompact(tracer);
}
// Always perform a scavenge to make room in new space.
Scavenge();
// Update the old space promotion limits after the scavenge due to
// promotions during scavenge.
if (collector == MARK_COMPACTOR) {
int old_gen_size = PromotedSpaceSize(); int old_gen_size = PromotedSpaceSize();
old_gen_promotion_limit_ = old_gen_promotion_limit_ =
old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3); old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3);
old_gen_allocation_limit_ = old_gen_allocation_limit_ =
old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 2); old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 2);
old_gen_exhausted_ = false; old_gen_exhausted_ = false;
} else {
Scavenge();
} }
Counters::objs_since_last_young.Set(0); Counters::objs_since_last_young.Set(0);
@ -759,17 +764,6 @@ static void VerifyNonPointerSpacePointers() {
#endif #endif
void Heap::CheckNewSpaceExpansionCriteria() {
if (new_space_.Capacity() < new_space_.MaximumCapacity() &&
survived_since_last_expansion_ > new_space_.Capacity()) {
// Grow the size of new space if there is room to grow and enough
// data has survived scavenge since the last expansion.
new_space_.Grow();
survived_since_last_expansion_ = 0;
}
}
void Heap::Scavenge() { void Heap::Scavenge() {
#ifdef DEBUG #ifdef DEBUG
if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers(); if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers();
@ -786,7 +780,13 @@ void Heap::Scavenge() {
// Used for updating survived_since_last_expansion_ at function end. // Used for updating survived_since_last_expansion_ at function end.
int survived_watermark = PromotedSpaceSize(); int survived_watermark = PromotedSpaceSize();
CheckNewSpaceExpansionCriteria(); if (new_space_.Capacity() < new_space_.MaximumCapacity() &&
survived_since_last_expansion_ > new_space_.Capacity()) {
// Grow the size of new space if there is room to grow and enough
// data has survived scavenge since the last expansion.
new_space_.Grow();
survived_since_last_expansion_ = 0;
}
// Flip the semispaces. After flipping, to space is empty, from space has // Flip the semispaces. After flipping, to space is empty, from space has
// live objects. // live objects.
@ -837,17 +837,15 @@ void Heap::Scavenge() {
new_space_front = DoScavenge(&scavenge_visitor, new_space_front); new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
UpdateNewSpaceReferencesInExternalStringTable( ScavengeExternalStringTable();
&UpdateNewSpaceReferenceInExternalStringTableEntry);
ASSERT(new_space_front == new_space_.top()); ASSERT(new_space_front == new_space_.top());
// Set age mark. // Set age mark.
new_space_.set_age_mark(new_space_.top()); new_space_.set_age_mark(new_space_.top());
// Update how much has survived scavenge. // Update how much has survived scavenge.
IncrementYoungSurvivorsCounter( survived_since_last_expansion_ +=
(PromotedSpaceSize() - survived_watermark) + new_space_.Size()); (PromotedSpaceSize() - survived_watermark) + new_space_.Size();
LOG(ResourceEvent("scavenge", "end")); LOG(ResourceEvent("scavenge", "end"));
@ -855,22 +853,7 @@ void Heap::Scavenge() {
} }
String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Object** p) { void Heap::ScavengeExternalStringTable() {
MapWord first_word = HeapObject::cast(*p)->map_word();
if (!first_word.IsForwardingAddress()) {
// Unreachable external string can be finalized.
FinalizeExternalString(String::cast(*p));
return NULL;
}
// String is still reachable.
return String::cast(first_word.ToForwardingAddress());
}
void Heap::UpdateNewSpaceReferencesInExternalStringTable(
ExternalStringTableUpdaterCallback updater_func) {
ExternalStringTable::Verify(); ExternalStringTable::Verify();
if (ExternalStringTable::new_space_strings_.is_empty()) return; if (ExternalStringTable::new_space_strings_.is_empty()) return;
@ -881,10 +864,16 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable(
for (Object** p = start; p < end; ++p) { for (Object** p = start; p < end; ++p) {
ASSERT(Heap::InFromSpace(*p)); ASSERT(Heap::InFromSpace(*p));
String* target = updater_func(p); MapWord first_word = HeapObject::cast(*p)->map_word();
if (target == NULL) continue; if (!first_word.IsForwardingAddress()) {
// Unreachable external string can be finalized.
FinalizeExternalString(String::cast(*p));
continue;
}
// String is still reachable.
String* target = String::cast(first_word.ToForwardingAddress());
ASSERT(target->IsExternalString()); ASSERT(target->IsExternalString());
if (Heap::InNewSpace(target)) { if (Heap::InNewSpace(target)) {

View File

@ -200,9 +200,6 @@ class GCTracer;
class HeapStats; class HeapStats;
typedef String* (*ExternalStringTableUpdaterCallback)(Object** pointer);
// The all static Heap captures the interface to the global object heap. // The all static Heap captures the interface to the global object heap.
// All JavaScript contexts by this process share the same object heap. // All JavaScript contexts by this process share the same object heap.
@ -947,30 +944,6 @@ class Heap : public AllStatic {
static void RecordStats(HeapStats* stats); static void RecordStats(HeapStats* stats);
// Copy block of memory from src to dst. Size of block should be aligned
// by pointer size.
static inline void CopyBlock(Object** dst, Object** src, int byte_size);
// Optimized version of memmove for blocks with pointer size aligned sizes and
// pointer size aligned addresses.
static inline void MoveBlock(Object** dst, Object** src, size_t byte_size);
// Check new space expansion criteria and expand semispaces if it was hit.
static void CheckNewSpaceExpansionCriteria();
static inline void IncrementYoungSurvivorsCounter(int survived) {
survived_since_last_expansion_ += survived;
}
static void UpdateNewSpaceReferencesInExternalStringTable(
ExternalStringTableUpdaterCallback updater_func);
// 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.
static inline bool ShouldBePromoted(Address old_address, int object_size);
static int MaxObjectSizeInNewSpace() { return kMaxObjectSizeInNewSpace; } static int MaxObjectSizeInNewSpace() { return kMaxObjectSizeInNewSpace; }
private: private:
@ -1167,10 +1140,7 @@ class Heap : public AllStatic {
// Performs a minor collection in new generation. // Performs a minor collection in new generation.
static void Scavenge(); static void Scavenge();
static void ScavengeExternalStringTable();
static String* UpdateNewSpaceReferenceInExternalStringTableEntry(
Object** pointer);
static Address DoScavenge(ObjectVisitor* scavenge_visitor, static Address DoScavenge(ObjectVisitor* scavenge_visitor,
Address new_space_front); Address new_space_front);
@ -1188,6 +1158,11 @@ class Heap : public AllStatic {
HeapObject* target, HeapObject* target,
int size); int size);
// 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.
static inline bool ShouldBePromoted(Address old_address, int object_size);
#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
// Record the copy of an object in the NewSpace's statistics. // Record the copy of an object in the NewSpace's statistics.
static void RecordCopiedObject(HeapObject* obj); static void RecordCopiedObject(HeapObject* obj);
@ -1206,6 +1181,9 @@ class Heap : public AllStatic {
// Slow part of scavenge object. // Slow part of scavenge object.
static void ScavengeObjectSlow(HeapObject** p, HeapObject* object); static void ScavengeObjectSlow(HeapObject** p, HeapObject* object);
// Copy memory from src to dst.
static inline void CopyBlock(Object** dst, Object** src, int byte_size);
// Initializes a function with a shared part and prototype. // Initializes a function with a shared part and prototype.
// Returns the function. // Returns the function.
// Note: this code was factored out of AllocateFunction such that // Note: this code was factored out of AllocateFunction such that

View File

@ -53,13 +53,13 @@ MarkCompactCollector::CollectorState MarkCompactCollector::state_ = IDLE;
// Counters used for debugging the marking phase of mark-compact or mark-sweep // Counters used for debugging the marking phase of mark-compact or mark-sweep
// collection. // collection.
int MarkCompactCollector::live_bytes_ = 0; int MarkCompactCollector::live_bytes_ = 0;
int MarkCompactCollector::live_young_objects_size_ = 0; int MarkCompactCollector::live_young_objects_ = 0;
int MarkCompactCollector::live_old_data_objects_size_ = 0; int MarkCompactCollector::live_old_data_objects_ = 0;
int MarkCompactCollector::live_old_pointer_objects_size_ = 0; int MarkCompactCollector::live_old_pointer_objects_ = 0;
int MarkCompactCollector::live_code_objects_size_ = 0; int MarkCompactCollector::live_code_objects_ = 0;
int MarkCompactCollector::live_map_objects_size_ = 0; int MarkCompactCollector::live_map_objects_ = 0;
int MarkCompactCollector::live_cell_objects_size_ = 0; int MarkCompactCollector::live_cell_objects_ = 0;
int MarkCompactCollector::live_lo_objects_size_ = 0; int MarkCompactCollector::live_lo_objects_ = 0;
#endif #endif
void MarkCompactCollector::CollectGarbage() { void MarkCompactCollector::CollectGarbage() {
@ -136,13 +136,13 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
#ifdef DEBUG #ifdef DEBUG
live_bytes_ = 0; live_bytes_ = 0;
live_young_objects_size_ = 0; live_young_objects_ = 0;
live_old_pointer_objects_size_ = 0; live_old_pointer_objects_ = 0;
live_old_data_objects_size_ = 0; live_old_data_objects_ = 0;
live_code_objects_size_ = 0; live_code_objects_ = 0;
live_map_objects_size_ = 0; live_map_objects_ = 0;
live_cell_objects_size_ = 0; live_cell_objects_ = 0;
live_lo_objects_size_ = 0; live_lo_objects_ = 0;
#endif #endif
} }
@ -742,21 +742,21 @@ static int CountMarkedCallback(HeapObject* obj) {
void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
live_bytes_ += obj->Size(); live_bytes_ += obj->Size();
if (Heap::new_space()->Contains(obj)) { if (Heap::new_space()->Contains(obj)) {
live_young_objects_size_ += obj->Size(); live_young_objects_++;
} else if (Heap::map_space()->Contains(obj)) { } else if (Heap::map_space()->Contains(obj)) {
ASSERT(obj->IsMap()); ASSERT(obj->IsMap());
live_map_objects_size_ += obj->Size(); live_map_objects_++;
} else if (Heap::cell_space()->Contains(obj)) { } else if (Heap::cell_space()->Contains(obj)) {
ASSERT(obj->IsJSGlobalPropertyCell()); ASSERT(obj->IsJSGlobalPropertyCell());
live_cell_objects_size_ += obj->Size(); live_cell_objects_++;
} else if (Heap::old_pointer_space()->Contains(obj)) { } else if (Heap::old_pointer_space()->Contains(obj)) {
live_old_pointer_objects_size_ += obj->Size(); live_old_pointer_objects_++;
} else if (Heap::old_data_space()->Contains(obj)) { } else if (Heap::old_data_space()->Contains(obj)) {
live_old_data_objects_size_ += obj->Size(); live_old_data_objects_++;
} else if (Heap::code_space()->Contains(obj)) { } else if (Heap::code_space()->Contains(obj)) {
live_code_objects_size_ += obj->Size(); live_code_objects_++;
} else if (Heap::lo_space()->Contains(obj)) { } else if (Heap::lo_space()->Contains(obj)) {
live_lo_objects_size_ += obj->Size(); live_lo_objects_++;
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
@ -1068,210 +1068,31 @@ void MarkCompactCollector::EncodeForwardingAddressesInPagedSpace(
} }
// We scavange new space simultaneously with sweeping. This is done in two static void SweepSpace(NewSpace* space) {
// passes.
// The first pass migrates all alive objects from one semispace to another or
// promotes them to old space. Forwading address is written directly into
// first word of object without any encoding. If object is dead we are writing
// NULL as a forwarding address.
// The second pass updates pointers to new space in all spaces. It is possible
// to encounter pointers to dead objects during traversal of remembered set for
// map space because remembered set bits corresponding to dead maps are cleared
// later during map space sweeping.
static void MigrateObject(Address dst, Address src, int size) {
Heap::CopyBlock(reinterpret_cast<Object**>(dst),
reinterpret_cast<Object**>(src),
size);
Memory::Address_at(src) = dst;
}
// Visitor for updating pointers from live objects in old spaces to new space.
// It does not expect to encounter pointers to dead objects.
class PointersToNewGenUpdatingVisitor: public ObjectVisitor {
public:
void VisitPointer(Object** p) {
UpdatePointer(p);
}
void VisitPointers(Object** start, Object** end) {
for (Object** p = start; p < end; p++) UpdatePointer(p);
}
void VisitCodeTarget(RelocInfo* rinfo) {
ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
VisitPointer(&target);
rinfo->set_target_address(Code::cast(target)->instruction_start());
}
void VisitDebugTarget(RelocInfo* rinfo) {
ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&
rinfo->IsPatchedReturnSequence());
Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
VisitPointer(&target);
rinfo->set_call_address(Code::cast(target)->instruction_start());
}
private:
void UpdatePointer(Object** p) {
if (!(*p)->IsHeapObject()) return;
HeapObject* obj = HeapObject::cast(*p);
Address old_addr = obj->address();
if (Heap::new_space()->Contains(obj)) {
ASSERT(Heap::InFromSpace(*p));
*p = HeapObject::FromAddress(Memory::Address_at(old_addr));
}
}
};
// Visitor for updating pointers from live objects in old spaces to new space.
// It can encounter pointers to dead objects in new space when traversing map
// space (see comment for MigrateObject).
static void UpdatePointerToNewGen(HeapObject** p) {
if (!(*p)->IsHeapObject()) return;
Address old_addr = (*p)->address();
ASSERT(Heap::InFromSpace(*p));
Address new_addr = Memory::Address_at(old_addr);
// Object pointed by *p is dead. Update is not required.
if (new_addr == NULL) return;
*p = HeapObject::FromAddress(new_addr);
}
static String* UpdateNewSpaceReferenceInExternalStringTableEntry(Object **p) {
Address old_addr = HeapObject::cast(*p)->address();
Address new_addr = Memory::Address_at(old_addr);
return String::cast(HeapObject::FromAddress(new_addr));
}
static bool TryPromoteObject(HeapObject* object, int object_size) {
Object* result;
if (object_size > Heap::MaxObjectSizeInPagedSpace()) {
result = Heap::lo_space()->AllocateRawFixedArray(object_size);
if (!result->IsFailure()) {
HeapObject* target = HeapObject::cast(result);
MigrateObject(target->address(), object->address(), object_size);
Heap::UpdateRSet(target);
return true;
}
} else {
OldSpace* target_space = Heap::TargetSpace(object);
ASSERT(target_space == Heap::old_pointer_space() ||
target_space == Heap::old_data_space());
result = target_space->AllocateRaw(object_size);
if (!result->IsFailure()) {
HeapObject* target = HeapObject::cast(result);
MigrateObject(target->address(), object->address(), object_size);
if (target_space == Heap::old_pointer_space()) {
Heap::UpdateRSet(target);
}
return true;
}
}
return false;
}
static void SweepNewSpace(NewSpace* space) {
Heap::CheckNewSpaceExpansionCriteria();
Address from_bottom = space->bottom();
Address from_top = space->top();
// Flip the semispaces. After flipping, to space is empty, from space has
// live objects.
space->Flip();
space->ResetAllocationInfo();
int size = 0;
int survivors_size = 0;
// First pass: traverse all objects in inactive semispace, remove marks,
// migrate live objects and write forwarding addresses.
for (Address current = from_bottom; current < from_top; current += size) {
HeapObject* object = HeapObject::FromAddress(current);
if (object->IsMarked()) {
object->ClearMark();
MarkCompactCollector::tracer()->decrement_marked_count();
size = object->Size();
survivors_size += size;
if (Heap::ShouldBePromoted(current, size) &&
TryPromoteObject(object, size)) {
continue;
}
// Promotion either failed or not required.
// Copy the content of the object.
Object* target = space->AllocateRaw(size);
// Allocation cannot fail at this point: semispaces are of equal size.
ASSERT(!target->IsFailure());
MigrateObject(HeapObject::cast(target)->address(), current, size);
} else {
size = object->Size();
Memory::Address_at(current) = NULL;
}
}
// Second pass: find pointers to new space and update them.
PointersToNewGenUpdatingVisitor updating_visitor;
// Update pointers in to space.
HeapObject* object; HeapObject* object;
for (Address current = space->bottom(); for (Address current = space->bottom();
current < space->top(); current < space->top();
current += object->Size()) { current += object->Size()) {
object = HeapObject::FromAddress(current); object = HeapObject::FromAddress(current);
if (object->IsMarked()) {
object->IterateBody(object->map()->instance_type(), object->ClearMark();
object->Size(), MarkCompactCollector::tracer()->decrement_marked_count();
&updating_visitor); } else {
} // We give non-live objects a map that will correctly give their size,
// since their existing map might not be live after the collection.
// Update roots. int size = object->Size();
Heap::IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE); if (size >= ByteArray::kHeaderSize) {
object->set_map(Heap::raw_unchecked_byte_array_map());
// Update pointers in old spaces. ByteArray::cast(object)->set_length(ByteArray::LengthFor(size));
Heap::IterateRSet(Heap::old_pointer_space(), &UpdatePointerToNewGen); } else {
Heap::IterateRSet(Heap::map_space(), &UpdatePointerToNewGen); ASSERT(size == kPointerSize);
Heap::lo_space()->IterateRSet(&UpdatePointerToNewGen); object->set_map(Heap::raw_unchecked_one_pointer_filler_map());
}
// Update pointers from cells. ASSERT(object->Size() == size);
HeapObjectIterator cell_iterator(Heap::cell_space());
for (HeapObject* cell = cell_iterator.next();
cell != NULL;
cell = cell_iterator.next()) {
if (cell->IsJSGlobalPropertyCell()) {
Address value_address =
reinterpret_cast<Address>(cell) +
(JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
} }
// The object is now unmarked for the call to Size() at the top of the
// loop.
} }
// Update pointers from external string table.
Heap::UpdateNewSpaceReferencesInExternalStringTable(
&UpdateNewSpaceReferenceInExternalStringTableEntry);
// All pointers were updated. Update auxiliary allocation info.
Heap::IncrementYoungSurvivorsCounter(survivors_size);
space->set_age_mark(space->top());
} }
@ -1561,12 +1382,10 @@ class MapCompact {
ASSERT(FreeListNode::IsFreeListNode(vacant_map)); ASSERT(FreeListNode::IsFreeListNode(vacant_map));
ASSERT(map_to_evacuate->IsMap()); ASSERT(map_to_evacuate->IsMap());
ASSERT(Map::kSize % 4 == 0); memcpy(
reinterpret_cast<void*>(vacant_map->address()),
Heap::CopyBlock(reinterpret_cast<Object**>(vacant_map->address()), reinterpret_cast<void*>(map_to_evacuate->address()),
reinterpret_cast<Object**>(map_to_evacuate->address()), Map::kSize);
Map::kSize);
ASSERT(vacant_map->IsMap()); // Due to memcpy above. ASSERT(vacant_map->IsMap()); // Due to memcpy above.
MapWord forwarding_map_word = MapWord::FromMap(vacant_map); MapWord forwarding_map_word = MapWord::FromMap(vacant_map);
@ -1646,11 +1465,10 @@ void MarkCompactCollector::SweepSpaces() {
SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock);
SweepSpace(Heap::code_space(), &DeallocateCodeBlock); SweepSpace(Heap::code_space(), &DeallocateCodeBlock);
SweepSpace(Heap::cell_space(), &DeallocateCellBlock); SweepSpace(Heap::cell_space(), &DeallocateCellBlock);
SweepNewSpace(Heap::new_space()); SweepSpace(Heap::new_space());
SweepSpace(Heap::map_space(), &DeallocateMapBlock); SweepSpace(Heap::map_space(), &DeallocateMapBlock);
int live_maps_size = Heap::map_space()->Size(); int live_maps = Heap::map_space()->Size() / Map::kSize;
int live_maps = live_maps_size / Map::kSize; ASSERT(live_map_objects_ == live_maps);
ASSERT(live_map_objects_size_ == live_maps_size);
if (Heap::map_space()->NeedsCompaction(live_maps)) { if (Heap::map_space()->NeedsCompaction(live_maps)) {
MapCompact map_compact(live_maps); MapCompact map_compact(live_maps);
@ -1682,7 +1500,7 @@ int MarkCompactCollector::IterateLiveObjectsInRange(
Address start, Address start,
Address end, Address end,
HeapObjectCallback size_func) { HeapObjectCallback size_func) {
int live_objects_size = 0; int live_objects = 0;
Address current = start; Address current = start;
while (current < end) { while (current < end) {
uint32_t encoded_map = Memory::uint32_at(current); uint32_t encoded_map = Memory::uint32_at(current);
@ -1691,12 +1509,11 @@ int MarkCompactCollector::IterateLiveObjectsInRange(
} else if (encoded_map == kMultiFreeEncoding) { } else if (encoded_map == kMultiFreeEncoding) {
current += Memory::int_at(current + kIntSize); current += Memory::int_at(current + kIntSize);
} else { } else {
int size = size_func(HeapObject::FromAddress(current)); live_objects++;
current += size; current += size_func(HeapObject::FromAddress(current));
live_objects_size += size;
} }
} }
return live_objects_size; return live_objects;
} }
@ -1822,36 +1639,36 @@ void MarkCompactCollector::UpdatePointers() {
Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
GlobalHandles::IterateWeakRoots(&updating_visitor); GlobalHandles::IterateWeakRoots(&updating_visitor);
int live_maps_size = IterateLiveObjects(Heap::map_space(), int live_maps = IterateLiveObjects(Heap::map_space(),
&UpdatePointersInOldObject);
int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(),
&UpdatePointersInOldObject);
int live_data_olds = IterateLiveObjects(Heap::old_data_space(),
&UpdatePointersInOldObject); &UpdatePointersInOldObject);
int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(), int live_codes = IterateLiveObjects(Heap::code_space(),
&UpdatePointersInOldObject); &UpdatePointersInOldObject);
int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(), int live_cells = IterateLiveObjects(Heap::cell_space(),
&UpdatePointersInOldObject); &UpdatePointersInOldObject);
int live_codes_size = IterateLiveObjects(Heap::code_space(), int live_news = IterateLiveObjects(Heap::new_space(),
&UpdatePointersInOldObject); &UpdatePointersInNewObject);
int live_cells_size = IterateLiveObjects(Heap::cell_space(),
&UpdatePointersInOldObject);
int live_news_size = IterateLiveObjects(Heap::new_space(),
&UpdatePointersInNewObject);
// Large objects do not move, the map word can be updated directly. // Large objects do not move, the map word can be updated directly.
LargeObjectIterator it(Heap::lo_space()); LargeObjectIterator it(Heap::lo_space());
for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) for (HeapObject* obj = it.next(); obj != NULL; obj = it.next())
UpdatePointersInNewObject(obj); UpdatePointersInNewObject(obj);
USE(live_maps_size); USE(live_maps);
USE(live_pointer_olds_size); USE(live_pointer_olds);
USE(live_data_olds_size); USE(live_data_olds);
USE(live_codes_size); USE(live_codes);
USE(live_cells_size); USE(live_cells);
USE(live_news_size); USE(live_news);
ASSERT(live_maps_size == live_map_objects_size_); ASSERT(live_maps == live_map_objects_);
ASSERT(live_data_olds_size == live_old_data_objects_size_); ASSERT(live_data_olds == live_old_data_objects_);
ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); ASSERT(live_pointer_olds == live_old_pointer_objects_);
ASSERT(live_codes_size == live_code_objects_size_); ASSERT(live_codes == live_code_objects_);
ASSERT(live_cells_size == live_cell_objects_size_); ASSERT(live_cells == live_cell_objects_);
ASSERT(live_news_size == live_young_objects_size_); ASSERT(live_news == live_young_objects_);
} }
@ -1966,31 +1783,27 @@ void MarkCompactCollector::RelocateObjects() {
#endif #endif
// Relocates objects, always relocate map objects first. Relocating // Relocates objects, always relocate map objects first. Relocating
// objects in other space relies on map objects to get object size. // objects in other space relies on map objects to get object size.
int live_maps_size = IterateLiveObjects(Heap::map_space(), int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject);
&RelocateMapObject); int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(),
int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(), &RelocateOldPointerObject);
&RelocateOldPointerObject); int live_data_olds = IterateLiveObjects(Heap::old_data_space(),
int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(), &RelocateOldDataObject);
&RelocateOldDataObject); int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject);
int live_codes_size = IterateLiveObjects(Heap::code_space(), int live_cells = IterateLiveObjects(Heap::cell_space(), &RelocateCellObject);
&RelocateCodeObject); int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject);
int live_cells_size = IterateLiveObjects(Heap::cell_space(),
&RelocateCellObject);
int live_news_size = IterateLiveObjects(Heap::new_space(),
&RelocateNewObject);
USE(live_maps_size); USE(live_maps);
USE(live_pointer_olds_size); USE(live_data_olds);
USE(live_data_olds_size); USE(live_pointer_olds);
USE(live_codes_size); USE(live_codes);
USE(live_cells_size); USE(live_cells);
USE(live_news_size); USE(live_news);
ASSERT(live_maps_size == live_map_objects_size_); ASSERT(live_maps == live_map_objects_);
ASSERT(live_data_olds_size == live_old_data_objects_size_); ASSERT(live_data_olds == live_old_data_objects_);
ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); ASSERT(live_pointer_olds == live_old_pointer_objects_);
ASSERT(live_codes_size == live_code_objects_size_); ASSERT(live_codes == live_code_objects_);
ASSERT(live_cells_size == live_cell_objects_size_); ASSERT(live_cells == live_cell_objects_);
ASSERT(live_news_size == live_young_objects_size_); ASSERT(live_news == live_young_objects_);
// Flip from and to spaces // Flip from and to spaces
Heap::new_space()->Flip(); Heap::new_space()->Flip();
@ -2008,9 +1821,6 @@ void MarkCompactCollector::RelocateObjects() {
PagedSpaces spaces; PagedSpaces spaces;
for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
space->MCCommitRelocationInfo(); space->MCCommitRelocationInfo();
Heap::CheckNewSpaceExpansionCriteria();
Heap::IncrementYoungSurvivorsCounter(live_news_size);
} }
@ -2030,10 +1840,7 @@ int MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
Address old_addr = obj->address(); Address old_addr = obj->address();
if (new_addr != old_addr) { if (new_addr != old_addr) {
// Move contents. memmove(new_addr, old_addr, Map::kSize); // copy contents
Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
reinterpret_cast<Object**>(old_addr),
Map::kSize);
} }
#ifdef DEBUG #ifdef DEBUG
@ -2089,10 +1896,7 @@ int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
Address old_addr = obj->address(); Address old_addr = obj->address();
if (new_addr != old_addr) { if (new_addr != old_addr) {
// Move contents. memmove(new_addr, old_addr, obj_size); // Copy contents
Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
reinterpret_cast<Object**>(old_addr),
obj_size);
} }
ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
@ -2136,10 +1940,7 @@ int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
Address old_addr = obj->address(); Address old_addr = obj->address();
if (new_addr != old_addr) { if (new_addr != old_addr) {
// Move contents. memmove(new_addr, old_addr, obj_size); // Copy contents.
Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
reinterpret_cast<Object**>(old_addr),
obj_size);
} }
HeapObject* copied_to = HeapObject::FromAddress(new_addr); HeapObject* copied_to = HeapObject::FromAddress(new_addr);
@ -2175,9 +1976,9 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
#endif #endif
// New and old addresses cannot overlap. // New and old addresses cannot overlap.
Heap::CopyBlock(reinterpret_cast<Object**>(new_addr), memcpy(reinterpret_cast<void*>(new_addr),
reinterpret_cast<Object**>(old_addr), reinterpret_cast<void*>(old_addr),
obj_size); obj_size);
#ifdef DEBUG #ifdef DEBUG
if (FLAG_gc_verbose) { if (FLAG_gc_verbose) {

View File

@ -407,26 +407,26 @@ class MarkCompactCollector: public AllStatic {
// Counters used for debugging the marking phase of mark-compact or // Counters used for debugging the marking phase of mark-compact or
// mark-sweep collection. // mark-sweep collection.
// Size of live objects in Heap::to_space_. // Number of live objects in Heap::to_space_.
static int live_young_objects_size_; static int live_young_objects_;
// Size of live objects in Heap::old_pointer_space_. // Number of live objects in Heap::old_pointer_space_.
static int live_old_pointer_objects_size_; static int live_old_pointer_objects_;
// Size of live objects in Heap::old_data_space_. // Number of live objects in Heap::old_data_space_.
static int live_old_data_objects_size_; static int live_old_data_objects_;
// Size of live objects in Heap::code_space_. // Number of live objects in Heap::code_space_.
static int live_code_objects_size_; static int live_code_objects_;
// Size of live objects in Heap::map_space_. // Number of live objects in Heap::map_space_.
static int live_map_objects_size_; static int live_map_objects_;
// Size of live objects in Heap::cell_space_. // Number of live objects in Heap::cell_space_.
static int live_cell_objects_size_; static int live_cell_objects_;
// Size of live objects in Heap::lo_space_. // Number of live objects in Heap::lo_space_.
static int live_lo_objects_size_; static int live_lo_objects_;
// Number of live bytes in this collection. // Number of live bytes in this collection.
static int live_bytes_; static int live_bytes_;

View File

@ -657,7 +657,7 @@ inline Dest BitCast(const Source& source) {
return dest; return dest;
} }
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_UTILS_H_ #endif // V8_UTILS_H_