[object-stats] Record feedback vector slots separately

Record the various types of feedback vector slot separately, to estimate
the relative impact of e.g. load ICs vs call ICs. Also, log the unused
(i.e. uninitialized or premonomorphic) ones separately.

Bug: v8:7266
Change-Id: Ie035cf48969e39f7156dfe523fd9218749b95cfe
Reviewed-on: https://chromium-review.googlesource.com/897813
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51067}
This commit is contained in:
Leszek Swirski 2018-02-02 13:48:01 +00:00 committed by Commit Bot
parent f4411a32cd
commit 02cf73ccbf
3 changed files with 141 additions and 51 deletions

View File

@ -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<Address>(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());
}
}

View File

@ -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 {

View File

@ -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',