Index: src/heap.cc |
diff --git a/src/heap.cc b/src/heap.cc |
index 02635ad356a0d945f3b2f062dcbbfda32a01092a..75ccc44d128ccf90118244644891e967231ee787 100644 |
--- a/src/heap.cc |
+++ b/src/heap.cc |
@@ -404,7 +404,7 @@ intptr_t Heap::SizeOfObjects() { |
intptr_t total = 0; |
AllSpaces spaces; |
for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { |
- total += space->Size(); |
+ total += space->SizeOfObjects(); |
} |
return total; |
} |
@@ -4408,13 +4408,10 @@ void Heap::RecordStats(HeapStats* stats, bool take_snapshot) { |
MemoryAllocator::Size() + MemoryAllocator::Available(); |
*stats->os_error = OS::GetLastError(); |
if (take_snapshot) { |
- HeapIterator iterator; |
+ HeapIterator iterator(HeapIterator::kPreciseFiltering); |
for (HeapObject* obj = iterator.next(); |
obj != NULL; |
obj = iterator.next()) { |
- // Note: snapshot won't be precise because IsFreeListNode returns true |
- // for any bytearray. |
- if (FreeListNode::IsFreeListNode(obj)) continue; |
InstanceType type = obj->map()->instance_type(); |
ASSERT(0 <= type && type <= LAST_TYPE); |
stats->objects_per_type[type]++; |
@@ -4769,7 +4766,17 @@ OldSpace* OldSpaces::next() { |
} |
-SpaceIterator::SpaceIterator() : current_space_(FIRST_SPACE), iterator_(NULL) { |
+SpaceIterator::SpaceIterator() |
+ : current_space_(FIRST_SPACE), |
+ iterator_(NULL), |
+ size_func_(NULL) { |
+} |
+ |
+ |
+SpaceIterator::SpaceIterator(HeapObjectCallback size_func) |
+ : current_space_(FIRST_SPACE), |
+ iterator_(NULL), |
+ size_func_(size_func) { |
} |
@@ -4807,25 +4814,25 @@ ObjectIterator* SpaceIterator::CreateIterator() { |
switch (current_space_) { |
case NEW_SPACE: |
- iterator_ = new SemiSpaceIterator(Heap::new_space()); |
+ iterator_ = new SemiSpaceIterator(Heap::new_space(), size_func_); |
break; |
case OLD_POINTER_SPACE: |
- iterator_ = new HeapObjectIterator(Heap::old_pointer_space()); |
+ iterator_ = new HeapObjectIterator(Heap::old_pointer_space(), size_func_); |
break; |
case OLD_DATA_SPACE: |
- iterator_ = new HeapObjectIterator(Heap::old_data_space()); |
+ iterator_ = new HeapObjectIterator(Heap::old_data_space(), size_func_); |
break; |
case CODE_SPACE: |
- iterator_ = new HeapObjectIterator(Heap::code_space()); |
+ iterator_ = new HeapObjectIterator(Heap::code_space(), size_func_); |
break; |
case MAP_SPACE: |
- iterator_ = new HeapObjectIterator(Heap::map_space()); |
+ iterator_ = new HeapObjectIterator(Heap::map_space(), size_func_); |
break; |
case CELL_SPACE: |
- iterator_ = new HeapObjectIterator(Heap::cell_space()); |
+ iterator_ = new HeapObjectIterator(Heap::cell_space(), size_func_); |
break; |
case LO_SPACE: |
- iterator_ = new LargeObjectIterator(Heap::lo_space()); |
+ iterator_ = new LargeObjectIterator(Heap::lo_space(), size_func_); |
break; |
} |
@@ -4835,7 +4842,54 @@ ObjectIterator* SpaceIterator::CreateIterator() { |
} |
-HeapIterator::HeapIterator() { |
+class FreeListNodesFilter { |
+ public: |
+ FreeListNodesFilter() { |
+ MarkFreeListNodes(); |
+ } |
+ |
+ inline bool IsFreeListNode(HeapObject* object) { |
+ if (object->IsMarked()) { |
+ object->ClearMark(); |
+ return true; |
+ } else { |
+ return false; |
+ } |
+ } |
+ |
+ private: |
+ void MarkFreeListNodes() { |
+ Heap::old_pointer_space()->MarkFreeListNodes(); |
+ Heap::old_data_space()->MarkFreeListNodes(); |
+ MarkCodeSpaceFreeListNodes(); |
+ Heap::map_space()->MarkFreeListNodes(); |
+ Heap::cell_space()->MarkFreeListNodes(); |
+ } |
+ |
+ void MarkCodeSpaceFreeListNodes() { |
+ // For code space, using FreeListNode::IsFreeListNode is OK. |
+ HeapObjectIterator iter(Heap::code_space()); |
+ for (HeapObject* obj = iter.next_object(); |
+ obj != NULL; |
+ obj = iter.next_object()) { |
+ if (FreeListNode::IsFreeListNode(obj)) obj->SetMark(); |
+ } |
+ } |
+ |
+ AssertNoAllocation no_alloc; |
+}; |
+ |
+ |
+HeapIterator::HeapIterator() |
+ : filtering_(HeapIterator::kNoFiltering), |
+ filter_(NULL) { |
+ Init(); |
+} |
+ |
+ |
+HeapIterator::HeapIterator(HeapIterator::FreeListNodesFiltering filtering) |
+ : filtering_(filtering), |
+ filter_(NULL) { |
Init(); |
} |
@@ -4847,20 +4901,44 @@ HeapIterator::~HeapIterator() { |
void HeapIterator::Init() { |
// Start the iteration. |
- space_iterator_ = new SpaceIterator(); |
+ if (filtering_ == kPreciseFiltering) { |
+ filter_ = new FreeListNodesFilter; |
+ space_iterator_ = |
+ new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject); |
+ } else { |
+ space_iterator_ = new SpaceIterator; |
+ } |
object_iterator_ = space_iterator_->next(); |
} |
void HeapIterator::Shutdown() { |
+#ifdef DEBUG |
+ // Assert that in precise mode we have iterated through all |
+ // objects. Otherwise, heap will be left in an inconsistent state. |
+ if (filtering_ == kPreciseFiltering) { |
+ ASSERT(object_iterator_ == NULL); |
+ } |
+#endif |
// Make sure the last iterator is deallocated. |
delete space_iterator_; |
space_iterator_ = NULL; |
object_iterator_ = NULL; |
+ delete filter_; |
+ filter_ = NULL; |
} |
HeapObject* HeapIterator::next() { |
+ if (filter_ == NULL) return NextObject(); |
+ |
+ HeapObject* obj = NextObject(); |
+ while (obj != NULL && filter_->IsFreeListNode(obj)) obj = NextObject(); |
+ return obj; |
+} |
+ |
+ |
+HeapObject* HeapIterator::NextObject() { |
// No iterator means we are done. |
if (object_iterator_ == NULL) return NULL; |