Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Unified Diff: src/heap/object-stats.cc

Issue 2181623002: [heap] ObjectStats: Cleanup and more FIXED_ARRAY sub types (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap/object-stats.h ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap/object-stats.cc
diff --git a/src/heap/object-stats.cc b/src/heap/object-stats.cc
index 93a74e655bce78a5a9bb7c6eb93a544e50cfbafe..1f2eef0c339f5cad848529133999c8a2af74920f 100644
--- a/src/heap/object-stats.cc
+++ b/src/heap/object-stats.cc
@@ -161,42 +161,69 @@ void ObjectStats::CheckpointObjectStats() {
Isolate* ObjectStats::isolate() { return heap()->isolate(); }
-void ObjectStatsCollector::CollectStatistics(ObjectStats* stats,
- HeapObject* obj) {
+void ObjectStatsCollector::CollectStatistics(HeapObject* obj) {
Map* map = obj->map();
- Heap* heap = obj->GetHeap();
// Record for the InstanceType.
int object_size = obj->Size();
- stats->RecordObjectStats(map->instance_type(), object_size);
+ stats_->RecordObjectStats(map->instance_type(), object_size);
// Record specific sub types where possible.
- if (obj->IsMap()) {
- RecordMapDetails(stats, heap, obj);
- }
- if (obj->IsCode()) {
- RecordCodeDetails(stats, heap, obj);
- }
+ if (obj->IsMap()) RecordMapDetails(Map::cast(obj));
+ if (obj->IsCode()) RecordCodeDetails(Code::cast(obj));
if (obj->IsSharedFunctionInfo()) {
- RecordSharedFunctionInfoDetails(stats, heap, obj);
- }
- if (obj->IsFixedArray()) {
- RecordFixedArrayDetails(stats, heap, obj);
- }
- if (obj->IsJSObject()) {
- RecordJSObjectDetails(stats, heap, JSObject::cast(obj));
+ RecordSharedFunctionInfoDetails(SharedFunctionInfo::cast(obj));
}
+ if (obj->IsFixedArray()) RecordFixedArrayDetails(FixedArray::cast(obj));
+ if (obj->IsJSObject()) RecordJSObjectDetails(JSObject::cast(obj));
if (obj->IsJSWeakCollection()) {
- RecordJSWeakCollectionDetails(stats, heap, JSWeakCollection::cast(obj));
+ RecordJSWeakCollectionDetails(JSWeakCollection::cast(obj));
}
- if (obj->IsScript()) {
- RecordScriptDetails(stats, heap, Script::cast(obj));
+ if (obj->IsJSCollection()) {
+ RecordJSCollectionDetails(JSObject::cast(obj));
}
+ if (obj->IsJSFunction()) RecordJSFunctionDetails(JSFunction::cast(obj));
+ if (obj->IsScript()) RecordScriptDetails(Script::cast(obj));
+}
+
+void ObjectStatsCollector::CollectGlobalStatistics() {
+ // Global FixedArrays.
+ RecordFixedArrayHelper(nullptr, heap_->weak_new_space_object_to_code_list(),
+ WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE, 0);
+ RecordFixedArrayHelper(nullptr, heap_->serialized_templates(),
+ SERIALIZED_TEMPLATES_SUB_TYPE, 0);
+ RecordFixedArrayHelper(nullptr, heap_->number_string_cache(),
+ NUMBER_STRING_CACHE_SUB_TYPE, 0);
+ RecordFixedArrayHelper(nullptr, heap_->single_character_string_cache(),
+ SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE, 0);
+ RecordFixedArrayHelper(nullptr, heap_->string_split_cache(),
+ STRING_SPLIT_CACHE_SUB_TYPE, 0);
+ RecordFixedArrayHelper(nullptr, heap_->regexp_multiple_cache(),
+ REGEXP_MULTIPLE_CACHE_SUB_TYPE, 0);
+ RecordFixedArrayHelper(nullptr, heap_->retained_maps(),
+ RETAINED_MAPS_SUB_TYPE, 0);
+
+ // Global weak FixedArrays.
+ RecordFixedArrayHelper(
+ nullptr, WeakFixedArray::cast(heap_->noscript_shared_function_infos()),
+ NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE, 0);
+ RecordFixedArrayHelper(nullptr, WeakFixedArray::cast(heap_->script_list()),
+ SCRIPT_LIST_SUB_TYPE, 0);
+
+ // Global hash tables.
+ RecordHashTableHelper(nullptr, heap_->string_table(), STRING_TABLE_SUB_TYPE);
+ RecordHashTableHelper(nullptr, heap_->weak_object_to_code_table(),
+ OBJECT_TO_CODE_SUB_TYPE);
+ RecordHashTableHelper(nullptr, heap_->code_stubs(),
+ CODE_STUBS_TABLE_SUB_TYPE);
+ RecordHashTableHelper(nullptr, heap_->intrinsic_function_names(),
+ INTRINSIC_FUNCTION_NAMES_SUB_TYPE);
+ RecordHashTableHelper(nullptr, heap_->empty_properties_dictionary(),
+ EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE);
}
static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) {
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_byte_array() &&
@@ -207,33 +234,57 @@ static bool CanRecordFixedArray(Heap* heap, FixedArrayBase* array) {
array != heap->empty_properties_dictionary();
}
+static bool IsCowArray(Heap* heap, FixedArrayBase* array) {
+ return array->map() == heap->fixed_cow_array_map();
+}
+
static bool SameLiveness(HeapObject* obj1, HeapObject* obj2) {
- return ObjectMarking::Color(obj1) == ObjectMarking::Color(obj2);
+ return obj1 == nullptr || obj2 == nullptr ||
+ 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);
+bool ObjectStatsCollector::RecordFixedArrayHelper(HeapObject* parent,
+ FixedArray* array,
+ int subtype,
+ size_t overhead) {
+ if (SameLiveness(parent, array) && CanRecordFixedArray(heap_, array) &&
+ !IsCowArray(heap_, array)) {
+ return stats_->RecordFixedArraySubTypeStats(array, subtype, array->Size(),
+ overhead);
}
+ return false;
}
-void ObjectStatsCollector::RecordJSObjectDetails(ObjectStats* stats, Heap* heap,
- JSObject* object) {
- DCHECK(object->IsJSObject());
+void ObjectStatsCollector::RecursivelyRecordFixedArrayHelper(HeapObject* parent,
+ FixedArray* array,
+ int subtype) {
+ if (RecordFixedArrayHelper(parent, array, subtype, 0)) {
+ for (int i = 0; i < array->length(); i++) {
+ if (array->get(i)->IsFixedArray()) {
+ RecursivelyRecordFixedArrayHelper(
+ parent, FixedArray::cast(array->get(i)), subtype);
+ }
+ }
+ }
+}
+template <class HashTable>
+void ObjectStatsCollector::RecordHashTableHelper(HeapObject* parent,
+ HashTable* array,
+ int subtype) {
+ int used = array->NumberOfElements() * HashTable::kEntrySize;
+ CHECK_GE(array->Size(), used);
+ size_t overhead = array->Size() - used;
+ RecordFixedArrayHelper(parent, array, subtype, overhead);
+}
+
+void ObjectStatsCollector::RecordJSObjectDetails(JSObject* object) {
size_t overhead = 0;
FixedArrayBase* elements = object->elements();
- if (CanRecordFixedArray(heap, elements)) {
+ if (CanRecordFixedArray(heap_, elements) && !IsCowArray(heap_, elements)) {
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(
- elements, DICTIONARY_ELEMENTS_SUB_TYPE, elements->Size(), overhead);
+ RecordHashTableHelper(object, dict, DICTIONARY_ELEMENTS_SUB_TYPE);
} else {
if (IsFastHoleyElementsKind(object->GetElementsKind())) {
int used = object->GetFastElementsUsage() * kPointerSize;
@@ -241,108 +292,131 @@ void ObjectStatsCollector::RecordJSObjectDetails(ObjectStats* stats, Heap* heap,
CHECK_GE(elements->Size(), used);
overhead = elements->Size() - used;
}
- stats->RecordFixedArraySubTypeStats(elements, FAST_ELEMENTS_SUB_TYPE,
- elements->Size(), overhead);
+ stats_->RecordFixedArraySubTypeStats(elements, FAST_ELEMENTS_SUB_TYPE,
+ elements->Size(), overhead);
}
}
overhead = 0;
FixedArrayBase* properties = object->properties();
- if (CanRecordFixedArray(heap, properties) &&
- SameLiveness(object, properties)) {
+ if (CanRecordFixedArray(heap_, properties) &&
+ SameLiveness(object, properties) && !IsCowArray(heap_, properties)) {
if (properties->IsDictionary()) {
NameDictionary* dict = NameDictionary::cast(properties);
- int used = dict->NumberOfElements() * NameDictionary::kEntrySize;
- CHECK_GE(properties->Size(), used);
- overhead = properties->Size() - used;
- stats->RecordFixedArraySubTypeStats(properties,
- DICTIONARY_PROPERTIES_SUB_TYPE,
- properties->Size(), overhead);
+ RecordHashTableHelper(object, dict, DICTIONARY_PROPERTIES_SUB_TYPE);
} else {
- stats->RecordFixedArraySubTypeStats(properties, FAST_PROPERTIES_SUB_TYPE,
- properties->Size(), overhead);
+ stats_->RecordFixedArraySubTypeStats(properties, FAST_PROPERTIES_SUB_TYPE,
+ properties->Size(), overhead);
}
}
}
void ObjectStatsCollector::RecordJSWeakCollectionDetails(
- ObjectStats* stats, Heap* heap, JSWeakCollection* obj) {
+ JSWeakCollection* obj) {
if (obj->table()->IsHashTable()) {
ObjectHashTable* table = ObjectHashTable::cast(obj->table());
int used = table->NumberOfElements() * ObjectHashTable::kEntrySize;
size_t overhead = table->Size() - used;
- RecordFixedArrayHelper(stats, heap, obj, table, WEAK_COLLECTION_SUB_TYPE,
- overhead);
+ RecordFixedArrayHelper(obj, table, JS_WEAK_COLLECTION_SUB_TYPE, overhead);
}
}
-void ObjectStatsCollector::RecordScriptDetails(ObjectStats* stats, Heap* heap,
- Script* obj) {
+void ObjectStatsCollector::RecordJSCollectionDetails(JSObject* obj) {
+ if (obj->IsJSMap()) {
+ RecordHashTableHelper(nullptr,
+ OrderedHashMap::cast(JSMap::cast(obj)->table()),
+ JS_COLLECTION_SUB_TYPE);
+ }
+ if (obj->IsJSSet()) {
+ RecordHashTableHelper(nullptr,
+ OrderedHashSet::cast(JSSet::cast(obj)->table()),
+ JS_COLLECTION_SUB_TYPE);
+ }
+}
+
+void ObjectStatsCollector::RecordScriptDetails(Script* obj) {
Object* infos = WeakFixedArray::cast(obj->shared_function_infos());
if (infos->IsWeakFixedArray())
- RecordFixedArrayHelper(stats, heap, obj, WeakFixedArray::cast(infos),
+ RecordFixedArrayHelper(obj, WeakFixedArray::cast(infos),
SHARED_FUNCTION_INFOS_SUB_TYPE, 0);
}
-void ObjectStatsCollector::RecordMapDetails(ObjectStats* stats, Heap* heap,
- HeapObject* obj) {
- Map* map_obj = Map::cast(obj);
- DCHECK(obj->map()->instance_type() == MAP_TYPE);
+void ObjectStatsCollector::RecordMapDetails(Map* map_obj) {
DescriptorArray* array = map_obj->instance_descriptors();
- if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array() &&
+ 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);
+ RecordFixedArrayHelper(map_obj, array, DESCRIPTOR_ARRAY_SUB_TYPE, 0);
if (array->HasEnumCache()) {
- RecordFixedArrayHelper(stats, heap, array, array->GetEnumCache(),
- ENUM_CACHE_SUB_TYPE, 0);
+ RecordFixedArrayHelper(array, array->GetEnumCache(), ENUM_CACHE_SUB_TYPE,
+ 0);
}
if (array->HasEnumIndicesCache()) {
- RecordFixedArrayHelper(stats, heap, array, array->GetEnumIndicesCache(),
+ RecordFixedArrayHelper(array, array->GetEnumIndicesCache(),
ENUM_INDICES_CACHE_SUB_TYPE, 0);
}
}
if (map_obj->has_code_cache()) {
- RecordFixedArrayHelper(stats, heap, map_obj, map_obj->code_cache(),
+ RecordFixedArrayHelper(map_obj, map_obj->code_cache(),
MAP_CODE_CACHE_SUB_TYPE, 0);
}
+
+ for (DependentCode* cur_dependent_code = map_obj->dependent_code();
+ cur_dependent_code != heap_->empty_fixed_array();
+ cur_dependent_code = DependentCode::cast(
+ cur_dependent_code->get(DependentCode::kNextLinkIndex))) {
+ RecordFixedArrayHelper(map_obj, cur_dependent_code, DEPENDENT_CODE_SUB_TYPE,
+ 0);
+ }
+
+ if (map_obj->is_prototype_map()) {
+ if (map_obj->prototype_info()->IsPrototypeInfo()) {
+ PrototypeInfo* info = PrototypeInfo::cast(map_obj->prototype_info());
+ Object* users = info->prototype_users();
+ if (users->IsWeakFixedArray()) {
+ RecordFixedArrayHelper(map_obj, WeakFixedArray::cast(users),
+ PROTOTYPE_USERS_SUB_TYPE, 0);
+ }
+ }
+ }
}
-void ObjectStatsCollector::RecordCodeDetails(ObjectStats* stats, Heap* heap,
- HeapObject* obj) {
- int object_size = obj->Size();
- DCHECK(obj->map()->instance_type() == CODE_TYPE);
- Code* code_obj = Code::cast(obj);
- stats->RecordCodeSubTypeStats(code_obj->kind(), code_obj->GetAge(),
- object_size);
- Code* code = Code::cast(obj);
- RecordFixedArrayHelper(stats, heap, code, code->deoptimization_data(),
+void ObjectStatsCollector::RecordCodeDetails(Code* code) {
+ stats_->RecordCodeSubTypeStats(code->kind(), code->GetAge(), code->Size());
+ RecordFixedArrayHelper(code, code->deoptimization_data(),
DEOPTIMIZATION_DATA_SUB_TYPE, 0);
- for (RelocIterator it(code); !it.done(); it.next()) {
+ RecordFixedArrayHelper(code, code->handler_table(), HANDLER_TABLE_SUB_TYPE,
+ 0);
+ int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
+ for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
Object* target = it.rinfo()->target_object();
if (target->IsFixedArray()) {
- RecordFixedArrayHelper(stats, heap, code, FixedArray::cast(target),
- EMBEDDED_OBJECT_SUB_TYPE, 0);
+ RecursivelyRecordFixedArrayHelper(code, FixedArray::cast(target),
+ EMBEDDED_OBJECT_SUB_TYPE);
}
}
}
}
-void ObjectStatsCollector::RecordSharedFunctionInfoDetails(ObjectStats* stats,
- Heap* heap,
- HeapObject* obj) {
- SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
+void ObjectStatsCollector::RecordSharedFunctionInfoDetails(
+ SharedFunctionInfo* sfi) {
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);
+ RecordFixedArrayHelper(sfi, scope_info, SCOPE_INFO_SUB_TYPE, 0);
+ TypeFeedbackMetadata* feedback_metadata = sfi->feedback_metadata();
+ if (!feedback_metadata->is_empty()) {
+ RecordFixedArrayHelper(sfi, feedback_metadata,
+ TYPE_FEEDBACK_METADATA_SUB_TYPE, 0);
+ UnseededNumberDictionary* names = UnseededNumberDictionary::cast(
+ feedback_metadata->get(TypeFeedbackMetadata::kNamesTableIndex));
+ RecordHashTableHelper(sfi, names, TYPE_FEEDBACK_METADATA_SUB_TYPE);
+ }
if (!sfi->OptimizedCodeMapIsCleared()) {
FixedArray* optimized_code_map = sfi->optimized_code_map();
+ RecordFixedArrayHelper(sfi, optimized_code_map, OPTIMIZED_CODE_MAP_SUB_TYPE,
+ 0);
// Optimized code map should be small, so skip accounting.
int len = optimized_code_map->length();
for (int i = SharedFunctionInfo::kEntriesStart; i < len;
@@ -359,73 +433,33 @@ void ObjectStatsCollector::RecordSharedFunctionInfoDetails(ObjectStats* stats,
literals = LiteralsArray::cast(slot);
}
if (literals != nullptr) {
- RecordFixedArrayHelper(stats, heap, sfi, literals,
- LITERALS_ARRAY_SUB_TYPE, 0);
- RecordFixedArrayHelper(stats, heap, sfi, literals->feedback_vector(),
+ RecordFixedArrayHelper(sfi, literals, LITERALS_ARRAY_SUB_TYPE, 0);
+ RecordFixedArrayHelper(sfi, literals->feedback_vector(),
TYPE_FEEDBACK_VECTOR_SUB_TYPE, 0);
}
}
}
}
-void ObjectStatsCollector::RecordFixedArrayDetails(ObjectStats* stats,
- Heap* heap,
- HeapObject* obj) {
- FixedArray* array = FixedArray::cast(obj);
-
- // Special fixed arrays.
- int subtype = -1;
- if (array == heap->weak_new_space_object_to_code_list())
- subtype = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE;
- if (array == heap->serialized_templates())
- subtype = SERIALIZED_TEMPLATES_SUB_TYPE;
- if (array == heap->string_table()) subtype = STRING_TABLE_SUB_TYPE;
- if (array == heap->number_string_cache())
- subtype = NUMBER_STRING_CACHE_SUB_TYPE;
- if (array == heap->single_character_string_cache())
- subtype = SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE;
- if (array == heap->string_split_cache())
- subtype = STRING_SPLIT_CACHE_SUB_TYPE;
- if (array == heap->regexp_multiple_cache())
- subtype = REGEXP_MULTIPLE_CACHE_SUB_TYPE;
- if (array->IsContext()) subtype = CONTEXT_SUB_TYPE;
- if (array->map() == heap->fixed_cow_array_map())
- subtype = COPY_ON_WRITE_SUB_TYPE;
- if (subtype != -1) {
- stats->RecordFixedArraySubTypeStats(array, subtype, array->Size(), 0);
- }
+void ObjectStatsCollector::RecordJSFunctionDetails(JSFunction* function) {
+ LiteralsArray* literals = function->literals();
+ RecordFixedArrayHelper(function, literals, LITERALS_ARRAY_SUB_TYPE, 0);
+ RecordFixedArrayHelper(function, literals->feedback_vector(),
+ TYPE_FEEDBACK_VECTOR_SUB_TYPE, 0);
+}
- // Special hash maps.
- if (array == heap->weak_object_to_code_table()) {
- WeakHashTable* table = reinterpret_cast<WeakHashTable*>(array);
- int used = table->NumberOfElements() * WeakHashTable::kEntrySize;
- CHECK_GE(array->Size(), used);
- size_t overhead = array->Size() - used;
- stats->RecordFixedArraySubTypeStats(table, OBJECT_TO_CODE_SUB_TYPE,
- table->Size(), overhead);
+void ObjectStatsCollector::RecordFixedArrayDetails(FixedArray* array) {
+ if (array->IsContext()) {
+ RecordFixedArrayHelper(nullptr, array, CONTEXT_SUB_TYPE, 0);
+ }
+ if (IsCowArray(heap_, array) && CanRecordFixedArray(heap_, array)) {
+ stats_->RecordFixedArraySubTypeStats(array, COPY_ON_WRITE_SUB_TYPE,
+ array->Size(), 0);
}
if (array->IsNativeContext()) {
Context* native_ctx = Context::cast(array);
- UnseededNumberDictionary* dict =
- native_ctx->template_instantiations_cache();
- int used = dict->NumberOfElements() * UnseededNumberDictionary::kEntrySize;
- size_t overhead = dict->Size() - used;
- RecordFixedArrayHelper(stats, heap, array, dict,
- TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE, overhead);
- }
- if (array == heap->code_stubs()) {
- UnseededNumberDictionary* dict = UnseededNumberDictionary::cast(array);
- int used = dict->NumberOfElements() * UnseededNumberDictionary::kEntrySize;
- size_t overhead = dict->Size() - used;
- stats->RecordFixedArraySubTypeStats(dict, CODE_STUBS_TABLE_SUB_TYPE,
- dict->Size(), overhead);
- }
- if (array == heap->intrinsic_function_names()) {
- NameDictionary* dict = NameDictionary::cast(array);
- int used = dict->NumberOfElements() * NameDictionary::kEntrySize;
- size_t overhead = dict->Size() - used;
- stats->RecordFixedArraySubTypeStats(dict, INTRINSIC_FUNCTION_NAMES_SUB_TYPE,
- dict->Size(), overhead);
+ RecordHashTableHelper(array, native_ctx->template_instantiations_cache(),
+ TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE);
}
}
« no previous file with comments | « src/heap/object-stats.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698