Index: src/mark-compact.cc |
=================================================================== |
--- src/mark-compact.cc (revision 4369) |
+++ src/mark-compact.cc (working copy) |
@@ -53,13 +53,13 @@ |
// Counters used for debugging the marking phase of mark-compact or mark-sweep |
// collection. |
int MarkCompactCollector::live_bytes_ = 0; |
-int MarkCompactCollector::live_young_objects_size_ = 0; |
-int MarkCompactCollector::live_old_data_objects_size_ = 0; |
-int MarkCompactCollector::live_old_pointer_objects_size_ = 0; |
-int MarkCompactCollector::live_code_objects_size_ = 0; |
-int MarkCompactCollector::live_map_objects_size_ = 0; |
-int MarkCompactCollector::live_cell_objects_size_ = 0; |
-int MarkCompactCollector::live_lo_objects_size_ = 0; |
+int MarkCompactCollector::live_young_objects_ = 0; |
+int MarkCompactCollector::live_old_data_objects_ = 0; |
+int MarkCompactCollector::live_old_pointer_objects_ = 0; |
+int MarkCompactCollector::live_code_objects_ = 0; |
+int MarkCompactCollector::live_map_objects_ = 0; |
+int MarkCompactCollector::live_cell_objects_ = 0; |
+int MarkCompactCollector::live_lo_objects_ = 0; |
#endif |
void MarkCompactCollector::CollectGarbage() { |
@@ -136,13 +136,13 @@ |
#ifdef DEBUG |
live_bytes_ = 0; |
- live_young_objects_size_ = 0; |
- live_old_pointer_objects_size_ = 0; |
- live_old_data_objects_size_ = 0; |
- live_code_objects_size_ = 0; |
- live_map_objects_size_ = 0; |
- live_cell_objects_size_ = 0; |
- live_lo_objects_size_ = 0; |
+ live_young_objects_ = 0; |
+ live_old_pointer_objects_ = 0; |
+ live_old_data_objects_ = 0; |
+ live_code_objects_ = 0; |
+ live_map_objects_ = 0; |
+ live_cell_objects_ = 0; |
+ live_lo_objects_ = 0; |
#endif |
} |
@@ -742,21 +742,21 @@ |
void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { |
live_bytes_ += obj->Size(); |
if (Heap::new_space()->Contains(obj)) { |
- live_young_objects_size_ += obj->Size(); |
+ live_young_objects_++; |
} else if (Heap::map_space()->Contains(obj)) { |
ASSERT(obj->IsMap()); |
- live_map_objects_size_ += obj->Size(); |
+ live_map_objects_++; |
} else if (Heap::cell_space()->Contains(obj)) { |
ASSERT(obj->IsJSGlobalPropertyCell()); |
- live_cell_objects_size_ += obj->Size(); |
+ live_cell_objects_++; |
} 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)) { |
- live_old_data_objects_size_ += obj->Size(); |
+ live_old_data_objects_++; |
} else if (Heap::code_space()->Contains(obj)) { |
- live_code_objects_size_ += obj->Size(); |
+ live_code_objects_++; |
} else if (Heap::lo_space()->Contains(obj)) { |
- live_lo_objects_size_ += obj->Size(); |
+ live_lo_objects_++; |
} else { |
UNREACHABLE(); |
} |
@@ -1068,210 +1068,31 @@ |
} |
-// We scavange new space simultaneously with sweeping. This is done in two |
-// 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. |
+static void SweepSpace(NewSpace* space) { |
HeapObject* object; |
for (Address current = space->bottom(); |
current < space->top(); |
current += object->Size()) { |
object = HeapObject::FromAddress(current); |
- |
- object->IterateBody(object->map()->instance_type(), |
- object->Size(), |
- &updating_visitor); |
- } |
- |
- // Update roots. |
- Heap::IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE); |
- |
- // Update pointers in old spaces. |
- Heap::IterateRSet(Heap::old_pointer_space(), &UpdatePointerToNewGen); |
- Heap::IterateRSet(Heap::map_space(), &UpdatePointerToNewGen); |
- Heap::lo_space()->IterateRSet(&UpdatePointerToNewGen); |
- |
- // Update pointers from cells. |
- 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)); |
+ if (object->IsMarked()) { |
+ object->ClearMark(); |
+ MarkCompactCollector::tracer()->decrement_marked_count(); |
+ } 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. |
+ int size = object->Size(); |
+ if (size >= ByteArray::kHeaderSize) { |
+ object->set_map(Heap::raw_unchecked_byte_array_map()); |
+ ByteArray::cast(object)->set_length(ByteArray::LengthFor(size)); |
+ } else { |
+ ASSERT(size == kPointerSize); |
+ object->set_map(Heap::raw_unchecked_one_pointer_filler_map()); |
+ } |
+ ASSERT(object->Size() == size); |
} |
+ // 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 @@ |
ASSERT(FreeListNode::IsFreeListNode(vacant_map)); |
ASSERT(map_to_evacuate->IsMap()); |
- ASSERT(Map::kSize % 4 == 0); |
- |
- Heap::CopyBlock(reinterpret_cast<Object**>(vacant_map->address()), |
- reinterpret_cast<Object**>(map_to_evacuate->address()), |
- Map::kSize); |
- |
+ memcpy( |
+ reinterpret_cast<void*>(vacant_map->address()), |
+ reinterpret_cast<void*>(map_to_evacuate->address()), |
+ Map::kSize); |
ASSERT(vacant_map->IsMap()); // Due to memcpy above. |
MapWord forwarding_map_word = MapWord::FromMap(vacant_map); |
@@ -1646,11 +1465,10 @@ |
SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); |
SweepSpace(Heap::code_space(), &DeallocateCodeBlock); |
SweepSpace(Heap::cell_space(), &DeallocateCellBlock); |
- SweepNewSpace(Heap::new_space()); |
+ SweepSpace(Heap::new_space()); |
SweepSpace(Heap::map_space(), &DeallocateMapBlock); |
- int live_maps_size = Heap::map_space()->Size(); |
- int live_maps = live_maps_size / Map::kSize; |
- ASSERT(live_map_objects_size_ == live_maps_size); |
+ int live_maps = Heap::map_space()->Size() / Map::kSize; |
+ ASSERT(live_map_objects_ == live_maps); |
if (Heap::map_space()->NeedsCompaction(live_maps)) { |
MapCompact map_compact(live_maps); |
@@ -1682,7 +1500,7 @@ |
Address start, |
Address end, |
HeapObjectCallback size_func) { |
- int live_objects_size = 0; |
+ int live_objects = 0; |
Address current = start; |
while (current < end) { |
uint32_t encoded_map = Memory::uint32_at(current); |
@@ -1691,12 +1509,11 @@ |
} else if (encoded_map == kMultiFreeEncoding) { |
current += Memory::int_at(current + kIntSize); |
} else { |
- int size = size_func(HeapObject::FromAddress(current)); |
- current += size; |
- live_objects_size += size; |
+ live_objects++; |
+ current += size_func(HeapObject::FromAddress(current)); |
} |
} |
- return live_objects_size; |
+ return live_objects; |
} |
@@ -1822,36 +1639,36 @@ |
Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); |
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); |
- int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(), |
- &UpdatePointersInOldObject); |
- int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(), |
- &UpdatePointersInOldObject); |
- int live_codes_size = IterateLiveObjects(Heap::code_space(), |
- &UpdatePointersInOldObject); |
- int live_cells_size = IterateLiveObjects(Heap::cell_space(), |
- &UpdatePointersInOldObject); |
- int live_news_size = IterateLiveObjects(Heap::new_space(), |
- &UpdatePointersInNewObject); |
+ int live_codes = IterateLiveObjects(Heap::code_space(), |
+ &UpdatePointersInOldObject); |
+ int live_cells = IterateLiveObjects(Heap::cell_space(), |
+ &UpdatePointersInOldObject); |
+ int live_news = IterateLiveObjects(Heap::new_space(), |
+ &UpdatePointersInNewObject); |
// Large objects do not move, the map word can be updated directly. |
LargeObjectIterator it(Heap::lo_space()); |
for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) |
UpdatePointersInNewObject(obj); |
- USE(live_maps_size); |
- USE(live_pointer_olds_size); |
- USE(live_data_olds_size); |
- USE(live_codes_size); |
- USE(live_cells_size); |
- USE(live_news_size); |
- ASSERT(live_maps_size == live_map_objects_size_); |
- ASSERT(live_data_olds_size == live_old_data_objects_size_); |
- ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); |
- ASSERT(live_codes_size == live_code_objects_size_); |
- ASSERT(live_cells_size == live_cell_objects_size_); |
- ASSERT(live_news_size == live_young_objects_size_); |
+ USE(live_maps); |
+ USE(live_pointer_olds); |
+ USE(live_data_olds); |
+ USE(live_codes); |
+ USE(live_cells); |
+ USE(live_news); |
+ ASSERT(live_maps == live_map_objects_); |
+ ASSERT(live_data_olds == live_old_data_objects_); |
+ ASSERT(live_pointer_olds == live_old_pointer_objects_); |
+ ASSERT(live_codes == live_code_objects_); |
+ ASSERT(live_cells == live_cell_objects_); |
+ ASSERT(live_news == live_young_objects_); |
} |
@@ -1966,31 +1783,27 @@ |
#endif |
// Relocates objects, always relocate map objects first. Relocating |
// objects in other space relies on map objects to get object size. |
- int live_maps_size = IterateLiveObjects(Heap::map_space(), |
- &RelocateMapObject); |
- int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(), |
- &RelocateOldPointerObject); |
- int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(), |
- &RelocateOldDataObject); |
- int live_codes_size = IterateLiveObjects(Heap::code_space(), |
- &RelocateCodeObject); |
- int live_cells_size = IterateLiveObjects(Heap::cell_space(), |
- &RelocateCellObject); |
- int live_news_size = IterateLiveObjects(Heap::new_space(), |
- &RelocateNewObject); |
+ int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject); |
+ int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), |
+ &RelocateOldPointerObject); |
+ int live_data_olds = IterateLiveObjects(Heap::old_data_space(), |
+ &RelocateOldDataObject); |
+ int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject); |
+ int live_cells = IterateLiveObjects(Heap::cell_space(), &RelocateCellObject); |
+ int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject); |
- USE(live_maps_size); |
- USE(live_pointer_olds_size); |
- USE(live_data_olds_size); |
- USE(live_codes_size); |
- USE(live_cells_size); |
- USE(live_news_size); |
- ASSERT(live_maps_size == live_map_objects_size_); |
- ASSERT(live_data_olds_size == live_old_data_objects_size_); |
- ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); |
- ASSERT(live_codes_size == live_code_objects_size_); |
- ASSERT(live_cells_size == live_cell_objects_size_); |
- ASSERT(live_news_size == live_young_objects_size_); |
+ USE(live_maps); |
+ USE(live_data_olds); |
+ USE(live_pointer_olds); |
+ USE(live_codes); |
+ USE(live_cells); |
+ USE(live_news); |
+ ASSERT(live_maps == live_map_objects_); |
+ ASSERT(live_data_olds == live_old_data_objects_); |
+ ASSERT(live_pointer_olds == live_old_pointer_objects_); |
+ ASSERT(live_codes == live_code_objects_); |
+ ASSERT(live_cells == live_cell_objects_); |
+ ASSERT(live_news == live_young_objects_); |
// Flip from and to spaces |
Heap::new_space()->Flip(); |
@@ -2008,9 +1821,6 @@ |
PagedSpaces spaces; |
for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) |
space->MCCommitRelocationInfo(); |
- |
- Heap::CheckNewSpaceExpansionCriteria(); |
- Heap::IncrementYoungSurvivorsCounter(live_news_size); |
} |
@@ -2030,10 +1840,7 @@ |
Address old_addr = obj->address(); |
if (new_addr != old_addr) { |
- // Move contents. |
- Heap::MoveBlock(reinterpret_cast<Object**>(new_addr), |
- reinterpret_cast<Object**>(old_addr), |
- Map::kSize); |
+ memmove(new_addr, old_addr, Map::kSize); // copy contents |
} |
#ifdef DEBUG |
@@ -2089,10 +1896,7 @@ |
Address old_addr = obj->address(); |
if (new_addr != old_addr) { |
- // Move contents. |
- Heap::MoveBlock(reinterpret_cast<Object**>(new_addr), |
- reinterpret_cast<Object**>(old_addr), |
- obj_size); |
+ memmove(new_addr, old_addr, obj_size); // Copy contents |
} |
ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); |
@@ -2136,10 +1940,7 @@ |
Address old_addr = obj->address(); |
if (new_addr != old_addr) { |
- // Move contents. |
- Heap::MoveBlock(reinterpret_cast<Object**>(new_addr), |
- reinterpret_cast<Object**>(old_addr), |
- obj_size); |
+ memmove(new_addr, old_addr, obj_size); // Copy contents. |
} |
HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
@@ -2175,9 +1976,9 @@ |
#endif |
// New and old addresses cannot overlap. |
- Heap::CopyBlock(reinterpret_cast<Object**>(new_addr), |
- reinterpret_cast<Object**>(old_addr), |
- obj_size); |
+ memcpy(reinterpret_cast<void*>(new_addr), |
+ reinterpret_cast<void*>(old_addr), |
+ obj_size); |
#ifdef DEBUG |
if (FLAG_gc_verbose) { |