Index: src/heap/object-stats.cc |
diff --git a/src/heap/object-stats.cc b/src/heap/object-stats.cc |
index 3c82c7f7852bf307ed6a1b4bd86577a2fc2fd8bc..bd986a3fbd01fa7bf0b19c2eb39349d8b8a9df82 100644 |
--- a/src/heap/object-stats.cc |
+++ b/src/heap/object-stats.cc |
@@ -25,6 +25,7 @@ void ObjectStats::ClearObjectStats(bool clear_last_time_stats) { |
memset(object_counts_last_time_, 0, sizeof(object_counts_last_time_)); |
memset(object_sizes_last_time_, 0, sizeof(object_sizes_last_time_)); |
} |
+ visited_fixed_array_sub_types_.clear(); |
} |
static void PrintJSONArray(size_t* array, const int len) { |
@@ -190,9 +191,29 @@ void ObjectStatsCollector::CollectStatistics(ObjectStats* stats, |
} |
static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) { |
- return array->map() != heap->fixed_cow_array_map() && |
+ return array->map()->instance_type() == FIXED_ARRAY_TYPE && |
+ array->map() != heap->fixed_cow_array_map() && |
array->map() != heap->fixed_double_array_map() && |
- array != heap->empty_fixed_array(); |
+ array != heap->empty_fixed_array() && |
+ array != heap->empty_byte_array() && |
+ array != heap->empty_literals_array() && |
+ array != heap->empty_sloppy_arguments_elements() && |
+ array != heap->empty_slow_element_dictionary() && |
+ array != heap->empty_descriptor_array() && |
+ array != heap->empty_properties_dictionary(); |
+} |
+ |
+static bool SameLiveness(HeapObject* obj1, HeapObject* obj2) { |
+ return ObjectMarking::Color(obj1) == ObjectMarking::Color(obj2); |
+} |
+ |
+void ObjectStatsCollector::RecordFixedArrayHelper( |
+ ObjectStats* stats, Heap* heap, HeapObject* parent, FixedArray* array, |
+ int subtype, size_t overhead) { |
+ if (SameLiveness(parent, array) && CanRecordFixedArray(heap, array)) { |
+ stats->RecordFixedArraySubTypeStats(array, subtype, array->Size(), |
+ overhead); |
+ } |
} |
void ObjectStatsCollector::RecordJSObjectDetails(ObjectStats* stats, Heap* heap, |
@@ -202,13 +223,13 @@ void ObjectStatsCollector::RecordJSObjectDetails(ObjectStats* stats, Heap* heap, |
size_t overhead = 0; |
FixedArrayBase* elements = object->elements(); |
if (CanRecordFixedArray(heap, elements)) { |
- if (elements->IsDictionary()) { |
- SeededNumberDictionary* dict = object->element_dictionary(); |
+ if (elements->IsDictionary() && SameLiveness(object, elements)) { |
+ SeededNumberDictionary* dict = SeededNumberDictionary::cast(elements); |
int used = dict->NumberOfElements() * SeededNumberDictionary::kEntrySize; |
CHECK_GE(elements->Size(), used); |
overhead = elements->Size() - used; |
- stats->RecordFixedArraySubTypeStats(DICTIONARY_ELEMENTS_SUB_TYPE, |
- elements->Size(), overhead); |
+ stats->RecordFixedArraySubTypeStats( |
+ elements, DICTIONARY_ELEMENTS_SUB_TYPE, elements->Size(), overhead); |
} else { |
if (IsFastHoleyElementsKind(object->GetElementsKind())) { |
int used = object->GetFastElementsUsage() * kPointerSize; |
@@ -216,23 +237,25 @@ void ObjectStatsCollector::RecordJSObjectDetails(ObjectStats* stats, Heap* heap, |
CHECK_GE(elements->Size(), used); |
overhead = elements->Size() - used; |
} |
- stats->RecordFixedArraySubTypeStats(FAST_ELEMENTS_SUB_TYPE, |
+ stats->RecordFixedArraySubTypeStats(elements, FAST_ELEMENTS_SUB_TYPE, |
elements->Size(), overhead); |
} |
} |
overhead = 0; |
FixedArrayBase* properties = object->properties(); |
- if (CanRecordFixedArray(heap, properties)) { |
+ if (CanRecordFixedArray(heap, properties) && |
+ SameLiveness(object, properties)) { |
if (properties->IsDictionary()) { |
- NameDictionary* dict = object->property_dictionary(); |
+ NameDictionary* dict = NameDictionary::cast(properties); |
int used = dict->NumberOfElements() * NameDictionary::kEntrySize; |
CHECK_GE(properties->Size(), used); |
overhead = properties->Size() - used; |
- stats->RecordFixedArraySubTypeStats(DICTIONARY_PROPERTIES_SUB_TYPE, |
+ stats->RecordFixedArraySubTypeStats(properties, |
+ DICTIONARY_PROPERTIES_SUB_TYPE, |
properties->Size(), overhead); |
} else { |
- stats->RecordFixedArraySubTypeStats(FAST_PROPERTIES_SUB_TYPE, |
+ stats->RecordFixedArraySubTypeStats(properties, FAST_PROPERTIES_SUB_TYPE, |
properties->Size(), overhead); |
} |
} |
@@ -244,8 +267,8 @@ void ObjectStatsCollector::RecordJSWeakCollectionDetails( |
ObjectHashTable* table = ObjectHashTable::cast(obj->table()); |
int used = table->NumberOfElements() * ObjectHashTable::kEntrySize; |
size_t overhead = table->Size() - used; |
- stats->RecordFixedArraySubTypeStats(WEAK_COLLECTION_SUB_TYPE, table->Size(), |
- overhead); |
+ RecordFixedArrayHelper(stats, heap, obj, table, WEAK_COLLECTION_SUB_TYPE, |
+ overhead); |
} |
} |
@@ -254,24 +277,23 @@ void ObjectStatsCollector::RecordMapDetails(ObjectStats* stats, Heap* heap, |
Map* map_obj = Map::cast(obj); |
DCHECK(obj->map()->instance_type() == MAP_TYPE); |
DescriptorArray* array = map_obj->instance_descriptors(); |
- if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array()) { |
- int fixed_array_size = array->Size(); |
- stats->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, |
- fixed_array_size, 0); |
+ if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array() && |
+ SameLiveness(map_obj, array)) { |
+ RecordFixedArrayHelper(stats, heap, map_obj, array, |
+ DESCRIPTOR_ARRAY_SUB_TYPE, 0); |
if (array->HasEnumCache()) { |
- stats->RecordFixedArraySubTypeStats(ENUM_CACHE_SUB_TYPE, |
- array->GetEnumCache()->Size(), 0); |
+ RecordFixedArrayHelper(stats, heap, array, array->GetEnumCache(), |
+ ENUM_CACHE_SUB_TYPE, 0); |
} |
if (array->HasEnumIndicesCache()) { |
- stats->RecordFixedArraySubTypeStats( |
- ENUM_INDICES_CACHE_SUB_TYPE, array->GetEnumIndicesCache()->Size(), 0); |
+ RecordFixedArrayHelper(stats, heap, array, array->GetEnumIndicesCache(), |
+ ENUM_INDICES_CACHE_SUB_TYPE, 0); |
} |
} |
if (map_obj->has_code_cache()) { |
- FixedArray* cache = map_obj->code_cache(); |
- stats->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, cache->Size(), |
- 0); |
+ RecordFixedArrayHelper(stats, heap, map_obj, map_obj->code_cache(), |
+ MAP_CODE_CACHE_SUB_TYPE, 0); |
} |
} |
@@ -283,36 +305,20 @@ void ObjectStatsCollector::RecordCodeDetails(ObjectStats* stats, Heap* heap, |
stats->RecordCodeSubTypeStats(code_obj->kind(), code_obj->GetAge(), |
object_size); |
Code* code = Code::cast(obj); |
- if (code->deoptimization_data() != heap->empty_fixed_array()) { |
- stats->RecordFixedArraySubTypeStats(DEOPTIMIZATION_DATA_SUB_TYPE, |
- code->deoptimization_data()->Size(), 0); |
- } |
- FixedArrayBase* reloc_info = |
- reinterpret_cast<FixedArrayBase*>(code->unchecked_relocation_info()); |
- if (reloc_info != heap->empty_fixed_array()) { |
- stats->RecordFixedArraySubTypeStats(RELOC_INFO_SUB_TYPE, |
- code->relocation_info()->Size(), 0); |
- } |
- FixedArrayBase* source_pos_table = |
- reinterpret_cast<FixedArrayBase*>(code->source_position_table()); |
- if (source_pos_table != heap->empty_fixed_array()) { |
- stats->RecordFixedArraySubTypeStats(SOURCE_POS_SUB_TYPE, |
- source_pos_table->Size(), 0); |
- } |
+ RecordFixedArrayHelper(stats, heap, code, code->deoptimization_data(), |
+ DEOPTIMIZATION_DATA_SUB_TYPE, 0); |
} |
void ObjectStatsCollector::RecordSharedFunctionInfoDetails(ObjectStats* stats, |
Heap* heap, |
HeapObject* obj) { |
SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj); |
- if (sfi->scope_info() != heap->empty_fixed_array()) { |
- stats->RecordFixedArraySubTypeStats(SCOPE_INFO_SUB_TYPE, |
- sfi->scope_info()->Size(), 0); |
- } |
- if (sfi->feedback_metadata() != heap->empty_fixed_array()) { |
- stats->RecordFixedArraySubTypeStats(TYPE_FEEDBACK_METADATA_SUB_TYPE, |
- sfi->feedback_metadata()->Size(), 0); |
- } |
+ FixedArray* scope_info = sfi->scope_info(); |
+ RecordFixedArrayHelper(stats, heap, sfi, scope_info, SCOPE_INFO_SUB_TYPE, 0); |
+ FixedArray* feedback_metadata = sfi->feedback_metadata(); |
+ RecordFixedArrayHelper(stats, heap, sfi, feedback_metadata, |
+ TYPE_FEEDBACK_METADATA_SUB_TYPE, 0); |
+ |
if (!sfi->OptimizedCodeMapIsCleared()) { |
FixedArray* optimized_code_map = sfi->optimized_code_map(); |
// Optimized code map should be small, so skip accounting. |
@@ -331,12 +337,10 @@ void ObjectStatsCollector::RecordSharedFunctionInfoDetails(ObjectStats* stats, |
literals = LiteralsArray::cast(slot); |
} |
if (literals != nullptr) { |
- stats->RecordFixedArraySubTypeStats(LITERALS_ARRAY_SUB_TYPE, |
- literals->Size(), 0); |
- TypeFeedbackVector* tfv = literals->feedback_vector(); |
- |
- stats->RecordFixedArraySubTypeStats(TYPE_FEEDBACK_VECTOR_SUB_TYPE, |
- tfv->Size(), 0); |
+ RecordFixedArrayHelper(stats, heap, sfi, literals, |
+ LITERALS_ARRAY_SUB_TYPE, 0); |
+ RecordFixedArrayHelper(stats, heap, sfi, literals->feedback_vector(), |
+ TYPE_FEEDBACK_VECTOR_SUB_TYPE, 0); |
} |
} |
} |
@@ -346,24 +350,22 @@ void ObjectStatsCollector::RecordFixedArrayDetails(ObjectStats* stats, |
Heap* heap, |
HeapObject* obj) { |
FixedArray* fixed_array = FixedArray::cast(obj); |
- if (fixed_array == heap->string_table()) { |
- stats->RecordFixedArraySubTypeStats(STRING_TABLE_SUB_TYPE, |
- fixed_array->Size(), 0); |
- } |
if (fixed_array == heap->weak_object_to_code_table()) { |
WeakHashTable* table = reinterpret_cast<WeakHashTable*>(fixed_array); |
int used = table->NumberOfElements() * WeakHashTable::kEntrySize; |
CHECK_GE(fixed_array->Size(), used); |
size_t overhead = fixed_array->Size() - used; |
- stats->RecordFixedArraySubTypeStats(OBJECT_TO_CODE_SUB_TYPE, |
+ stats->RecordFixedArraySubTypeStats(table, OBJECT_TO_CODE_SUB_TYPE, |
fixed_array->Size(), overhead); |
} |
- if (obj->IsContext()) { |
- stats->RecordFixedArraySubTypeStats(CONTEXT_SUB_TYPE, fixed_array->Size(), |
- 0); |
- } |
- if (fixed_array->map() == heap->fixed_cow_array_map()) { |
- stats->RecordFixedArraySubTypeStats(COPY_ON_WRITE_SUB_TYPE, |
+ |
+ int subtype = -1; |
+ if (fixed_array == heap->string_table()) subtype = STRING_TABLE_SUB_TYPE; |
+ if (fixed_array->IsContext()) subtype = CONTEXT_SUB_TYPE; |
+ if (fixed_array->map() == heap->fixed_cow_array_map()) |
+ subtype = COPY_ON_WRITE_SUB_TYPE; |
+ if (subtype != -1) { |
+ stats->RecordFixedArraySubTypeStats(fixed_array, subtype, |
fixed_array->Size(), 0); |
} |
} |