diff --git a/src/heap/object-stats.cc b/src/heap/object-stats.cc index 5b289f4e74..e72fc8b8ab 100644 --- a/src/heap/object-stats.cc +++ b/src/heap/object-stats.cc @@ -404,17 +404,89 @@ void ObjectStatsCollectorImpl::RecordVirtualJSObjectDetails(JSObject* object) { RecordSimpleVirtualObjectStats(object, elements, ObjectStats::ELEMENTS_TYPE); } +static ObjectStats::VirtualInstanceType GetFeedbackSlotType( + Object* obj, FeedbackSlotKind kind, Isolate* isolate) { + switch (kind) { + case FeedbackSlotKind::kCall: + if (obj == *isolate->factory()->uninitialized_symbol() || + obj == *isolate->factory()->premonomorphic_symbol()) { + return ObjectStats::FEEDBACK_VECTOR_SLOT_CALL_UNUSED_TYPE; + } + return ObjectStats::FEEDBACK_VECTOR_SLOT_CALL_TYPE; + + case FeedbackSlotKind::kLoadProperty: + case FeedbackSlotKind::kLoadGlobalInsideTypeof: + case FeedbackSlotKind::kLoadGlobalNotInsideTypeof: + case FeedbackSlotKind::kLoadKeyed: + if (obj == *isolate->factory()->uninitialized_symbol() || + obj == *isolate->factory()->premonomorphic_symbol()) { + return ObjectStats::FEEDBACK_VECTOR_SLOT_LOAD_UNUSED_TYPE; + } + return ObjectStats::FEEDBACK_VECTOR_SLOT_LOAD_TYPE; + + case FeedbackSlotKind::kStoreNamedSloppy: + case FeedbackSlotKind::kStoreNamedStrict: + case FeedbackSlotKind::kStoreOwnNamed: + case FeedbackSlotKind::kStoreGlobalSloppy: + case FeedbackSlotKind::kStoreGlobalStrict: + case FeedbackSlotKind::kStoreKeyedSloppy: + case FeedbackSlotKind::kStoreKeyedStrict: + if (obj == *isolate->factory()->uninitialized_symbol() || + obj == *isolate->factory()->premonomorphic_symbol()) { + return ObjectStats::FEEDBACK_VECTOR_SLOT_STORE_UNUSED_TYPE; + } + return ObjectStats::FEEDBACK_VECTOR_SLOT_STORE_TYPE; + + case FeedbackSlotKind::kBinaryOp: + case FeedbackSlotKind::kCompareOp: + return ObjectStats::FEEDBACK_VECTOR_SLOT_ENUM_TYPE; + + default: + return ObjectStats::FEEDBACK_VECTOR_SLOT_OTHER_TYPE; + } +} + void ObjectStatsCollectorImpl::RecordVirtualFeedbackVectorDetails( FeedbackVector* vector) { - // Except for allocation - for (int i = 0; i < vector->length(); i++) { - Object* raw_object = vector->get(i); - if (!raw_object->IsHeapObject()) continue; - HeapObject* object = HeapObject::cast(raw_object); - if (object->IsCell() || object->IsFixedArray()) { - RecordSimpleVirtualObjectStats(vector, object, - ObjectStats::FEEDBACK_VECTOR_ENTRY_TYPE); + if (virtual_objects_.find(vector) == virtual_objects_.end()) { + // Manually insert the feedback vector into the virtual object list, since + // we're logging its component parts separately. + virtual_objects_.insert(vector); + + size_t calculated_size = 0; + + // Log the feedback vector's header (fixed fields). + size_t header_size = + reinterpret_cast
(vector->slots_start()) - vector->address(); + stats_->RecordVirtualObjectStats(ObjectStats::FEEDBACK_VECTOR_HEADER_TYPE, + header_size, + ObjectStats::kNoOverAllocation); + calculated_size += header_size; + + // Iterate over the feedback slots and log each one. + FeedbackMetadataIterator it(vector->metadata()); + while (it.HasNext()) { + FeedbackSlot slot = it.Next(); + // Log the entry (or entries) taken up by this slot. + size_t slot_size = it.entry_size() * kPointerSize; + stats_->RecordVirtualObjectStats( + GetFeedbackSlotType(vector->Get(slot), it.kind(), heap_->isolate()), + slot_size, ObjectStats::kNoOverAllocation); + calculated_size += slot_size; + + // Log the monomorphic/polymorphic helper objects that this slot owns. + for (int i = 0; i < it.entry_size(); i++) { + Object* raw_object = vector->get(slot.ToInt() + i); + if (!raw_object->IsHeapObject()) continue; + HeapObject* object = HeapObject::cast(raw_object); + if (object->IsCell() || object->IsFixedArray()) { + RecordSimpleVirtualObjectStats( + vector, object, ObjectStats::FEEDBACK_VECTOR_ENTRY_TYPE); + } + } } + + CHECK_EQ(calculated_size, vector->Size()); } } diff --git a/src/heap/object-stats.h b/src/heap/object-stats.h index 15b1f73dad..2d6b278877 100644 --- a/src/heap/object-stats.h +++ b/src/heap/object-stats.h @@ -14,49 +14,58 @@ // tracing. // // Update LAST_VIRTUAL_TYPE below when changing this macro. -#define VIRTUAL_INSTANCE_TYPE_LIST(V) \ - CODE_KIND_LIST(V) \ - V(BOILERPLATE_ELEMENTS_TYPE) \ - V(BOILERPLATE_PROPERTY_ARRAY_TYPE) \ - V(BOILERPLATE_PROPERTY_DICTIONARY_TYPE) \ - V(BYTECODE_ARRAY_CONSTANT_POOL_TYPE) \ - V(BYTECODE_ARRAY_HANDLER_TABLE_TYPE) \ - V(CODE_STUBS_TABLE_TYPE) \ - V(COW_ARRAY_TYPE) \ - V(DEOPTIMIZATION_DATA_TYPE) \ - V(DEPENDENT_CODE_TYPE) \ - V(ELEMENTS_TYPE) \ - V(EMBEDDED_OBJECT_TYPE) \ - V(ENUM_CACHE_TYPE) \ - V(ENUM_INDICES_CACHE_TYPE) \ - V(FEEDBACK_METADATA_TYPE) \ - V(FEEDBACK_VECTOR_ENTRY_TYPE) \ - V(FUNCTION_CONTEXT_TYPE) \ - V(FUNCTION_TEMPLATE_INFO_ENTRIES_TYPE) \ - V(GLOBAL_ELEMENTS_TYPE) \ - V(GLOBAL_PROPERTIES_TYPE) \ - V(JS_ARRAY_BOILERPLATE_TYPE) \ - V(JS_COLLETION_TABLE_TYPE) \ - V(JS_OBJECT_BOILERPLATE_TYPE) \ - V(NATIVE_CONTEXT_TYPE) \ - V(NOSCRIPT_SHARED_FUNCTION_INFOS_TYPE) \ - V(NUMBER_STRING_CACHE_TYPE) \ - V(OBJECT_PROPERTY_DICTIONARY_TYPE) \ - V(OBJECT_TO_CODE_TYPE) \ - V(OPTIMIZED_CODE_LITERALS_TYPE) \ - V(OTHER_CONTEXT_TYPE) \ - V(PROTOTYPE_USERS_TYPE) \ - V(REGEXP_MULTIPLE_CACHE_TYPE) \ - V(RETAINED_MAPS_TYPE) \ - V(SCOPE_INFO_TYPE) \ - V(SCRIPT_LIST_TYPE) \ - V(SCRIPT_SHARED_FUNCTION_INFOS_TYPE) \ - V(SERIALIZED_OBJECTS_TYPE) \ - V(SINGLE_CHARACTER_STRING_CACHE_TYPE) \ - V(STRING_SPLIT_CACHE_TYPE) \ - V(STRING_TABLE_TYPE) \ - V(UNCOMPILED_JS_FUNCTION_TYPE) \ - V(UNCOMPILED_SHARED_FUNCTION_INFO_TYPE) \ +#define VIRTUAL_INSTANCE_TYPE_LIST(V) \ + CODE_KIND_LIST(V) \ + V(BOILERPLATE_ELEMENTS_TYPE) \ + V(BOILERPLATE_PROPERTY_ARRAY_TYPE) \ + V(BOILERPLATE_PROPERTY_DICTIONARY_TYPE) \ + V(BYTECODE_ARRAY_CONSTANT_POOL_TYPE) \ + V(BYTECODE_ARRAY_HANDLER_TABLE_TYPE) \ + V(CODE_STUBS_TABLE_TYPE) \ + V(COW_ARRAY_TYPE) \ + V(DEOPTIMIZATION_DATA_TYPE) \ + V(DEPENDENT_CODE_TYPE) \ + V(ELEMENTS_TYPE) \ + V(EMBEDDED_OBJECT_TYPE) \ + V(ENUM_CACHE_TYPE) \ + V(ENUM_INDICES_CACHE_TYPE) \ + V(FEEDBACK_METADATA_TYPE) \ + V(FEEDBACK_VECTOR_ENTRY_TYPE) \ + V(FEEDBACK_VECTOR_HEADER_TYPE) \ + V(FEEDBACK_VECTOR_SLOT_CALL_TYPE) \ + V(FEEDBACK_VECTOR_SLOT_CALL_UNUSED_TYPE) \ + V(FEEDBACK_VECTOR_SLOT_ENUM_TYPE) \ + V(FEEDBACK_VECTOR_SLOT_LOAD_TYPE) \ + V(FEEDBACK_VECTOR_SLOT_LOAD_UNUSED_TYPE) \ + V(FEEDBACK_VECTOR_SLOT_OTHER_TYPE) \ + V(FEEDBACK_VECTOR_SLOT_STORE_TYPE) \ + V(FEEDBACK_VECTOR_SLOT_STORE_UNUSED_TYPE) \ + V(FUNCTION_CONTEXT_TYPE) \ + V(FUNCTION_TEMPLATE_INFO_ENTRIES_TYPE) \ + V(GLOBAL_ELEMENTS_TYPE) \ + V(GLOBAL_PROPERTIES_TYPE) \ + V(JS_ARRAY_BOILERPLATE_TYPE) \ + V(JS_COLLETION_TABLE_TYPE) \ + V(JS_OBJECT_BOILERPLATE_TYPE) \ + V(NATIVE_CONTEXT_TYPE) \ + V(NOSCRIPT_SHARED_FUNCTION_INFOS_TYPE) \ + V(NUMBER_STRING_CACHE_TYPE) \ + V(OBJECT_PROPERTY_DICTIONARY_TYPE) \ + V(OBJECT_TO_CODE_TYPE) \ + V(OPTIMIZED_CODE_LITERALS_TYPE) \ + V(OTHER_CONTEXT_TYPE) \ + V(PROTOTYPE_USERS_TYPE) \ + V(REGEXP_MULTIPLE_CACHE_TYPE) \ + V(RETAINED_MAPS_TYPE) \ + V(SCOPE_INFO_TYPE) \ + V(SCRIPT_LIST_TYPE) \ + V(SCRIPT_SHARED_FUNCTION_INFOS_TYPE) \ + V(SERIALIZED_OBJECTS_TYPE) \ + V(SINGLE_CHARACTER_STRING_CACHE_TYPE) \ + V(STRING_SPLIT_CACHE_TYPE) \ + V(STRING_TABLE_TYPE) \ + V(UNCOMPILED_JS_FUNCTION_TYPE) \ + V(UNCOMPILED_SHARED_FUNCTION_INFO_TYPE) \ V(WEAK_NEW_SPACE_OBJECT_TO_CODE_TYPE) namespace v8 { diff --git a/tools/heap-stats/categories.js b/tools/heap-stats/categories.js index d540345e06..08cd6560d7 100644 --- a/tools/heap-stats/categories.js +++ b/tools/heap-stats/categories.js @@ -144,7 +144,16 @@ const CATEGORIES = new Map([ 'DEOPTIMIZATION_DATA_TYPE', 'EMBEDDED_OBJECT_TYPE', 'FEEDBACK_METADATA_TYPE', + 'FEEDBACK_VECTOR_HEADER_TYPE', 'FEEDBACK_VECTOR_ENTRY_TYPE', + 'FEEDBACK_VECTOR_SLOT_CALL_TYPE', + 'FEEDBACK_VECTOR_SLOT_CALL_UNUSED_TYPE', + 'FEEDBACK_VECTOR_SLOT_ENUM_TYPE', + 'FEEDBACK_VECTOR_SLOT_LOAD_TYPE', + 'FEEDBACK_VECTOR_SLOT_LOAD_UNUSED_TYPE', + 'FEEDBACK_VECTOR_SLOT_OTHER_TYPE', + 'FEEDBACK_VECTOR_SLOT_STORE_TYPE', + 'FEEDBACK_VECTOR_SLOT_STORE_UNUSED_TYPE', 'FEEDBACK_VECTOR_TYPE', 'LOAD_HANDLER_TYPE', 'NOSCRIPT_SHARED_FUNCTION_INFOS_TYPE',