Commit ee72b7a1 authored by Seth Brenith's avatar Seth Brenith Committed by V8 LUCI CQ

Categorize object shape info in heap snapshots

One of the biggest categories in heap snapshots is named “(system)”,
which gives developers no indication of why all that memory is used or
what they might do to reduce it. In this change, I propose that we
create a new category for Maps, DescriptorArrays, and related objects,
and call this new category “(object shape)” in the devtools. I think
that this category name would be more meaningful, while still grouping
those objects together so that they mostly stay out of the way.

Bug: v8:12769
Doc: https://docs.google.com/document/d/1a-6V_2LIJuRcsppwh6E18g8OSnC9j6gN4ao2gq--BiU
Change-Id: I282a7b87c34ca6ed371ff32f3c7332d794ae42ca
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3587974Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#80123}
parent 370cae1d
......@@ -542,7 +542,9 @@ class V8_EXPORT HeapGraphNode {
kConsString = 10, // Concatenated string. A pair of pointers to strings.
kSlicedString = 11, // Sliced string. A fragment of another string.
kSymbol = 12, // A Symbol (ES6).
kBigInt = 13 // BigInt.
kBigInt = 13, // BigInt.
kObjectShape = 14, // Internal data used for tracking the shapes (or
// "hidden classes") of JS objects.
};
/** Returns node type (see HeapGraphNode::Type). */
......
......@@ -380,6 +380,8 @@ const char* HeapEntry::TypeAsString() const {
case kSymbol: return "/symbol/";
case kBigInt:
return "/bigint/";
case kObjectShape:
return "/object shape/";
default: return "???";
}
}
......@@ -955,6 +957,17 @@ HeapEntry::Type V8HeapExplorer::GetSystemEntryType(HeapObject object) {
return HeapEntry::kArray;
}
// Maps in read-only space are for internal V8 data, not user-defined object
// shapes.
if ((InstanceTypeChecker::IsMap(type) &&
!BasicMemoryChunk::FromHeapObject(object)->InReadOnlySpace()) ||
InstanceTypeChecker::IsDescriptorArray(type) ||
InstanceTypeChecker::IsTransitionArray(type) ||
InstanceTypeChecker::IsPrototypeInfo(type) ||
InstanceTypeChecker::IsEnumCache(type)) {
return HeapEntry::kObjectShape;
}
return HeapEntry::kHidden;
}
......@@ -1098,6 +1111,8 @@ void V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject obj) {
ExtractFeedbackCellReferences(entry, FeedbackCell::cast(obj));
} else if (obj.IsPropertyCell()) {
ExtractPropertyCellReferences(entry, PropertyCell::cast(obj));
} else if (obj.IsPrototypeInfo()) {
ExtractPrototypeInfoReferences(entry, PrototypeInfo::cast(obj));
} else if (obj.IsAllocationSite()) {
ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj));
} else if (obj.IsArrayBoilerplateDescription()) {
......@@ -1110,6 +1125,10 @@ void V8HeapExplorer::ExtractReferences(HeapEntry* entry, HeapObject obj) {
ExtractFeedbackVectorReferences(entry, FeedbackVector::cast(obj));
} else if (obj.IsDescriptorArray()) {
ExtractDescriptorArrayReferences(entry, DescriptorArray::cast(obj));
} else if (obj.IsEnumCache()) {
ExtractEnumCacheReferences(entry, EnumCache::cast(obj));
} else if (obj.IsTransitionArray()) {
ExtractTransitionArrayReferences(entry, TransitionArray::cast(obj));
} else if (obj.IsWeakFixedArray()) {
ExtractWeakArrayReferences(WeakFixedArray::kHeaderSize, entry,
WeakFixedArray::cast(obj));
......@@ -1412,6 +1431,8 @@ void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map map) {
TagObject(map.dependent_code(), "(dependent code)");
SetInternalReference(entry, "dependent_code", map.dependent_code(),
Map::kDependentCodeOffset);
TagObject(map.prototype_validity_cell(), "(prototype validity cell)",
HeapEntry::kObjectShape);
}
void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
......@@ -1556,6 +1577,14 @@ void V8HeapExplorer::ExtractPropertyCellReferences(HeapEntry* entry,
PropertyCell::kDependentCodeOffset);
}
void V8HeapExplorer::ExtractPrototypeInfoReferences(HeapEntry* entry,
PrototypeInfo info) {
TagObject(info.prototype_chain_enum_cache(), "(prototype chain enum cache)",
HeapEntry::kObjectShape);
TagObject(info.prototype_users(), "(prototype users)",
HeapEntry::kObjectShape);
}
void V8HeapExplorer::ExtractAllocationSiteReferences(HeapEntry* entry,
AllocationSite site) {
SetInternalReference(entry, "transition_info",
......@@ -1723,6 +1752,20 @@ void V8HeapExplorer::ExtractDescriptorArrayReferences(HeapEntry* entry,
}
}
void V8HeapExplorer::ExtractEnumCacheReferences(HeapEntry* entry,
EnumCache cache) {
TagObject(cache.keys(), "(enum cache)", HeapEntry::kObjectShape);
TagObject(cache.indices(), "(enum cache)", HeapEntry::kObjectShape);
}
void V8HeapExplorer::ExtractTransitionArrayReferences(
HeapEntry* entry, TransitionArray transitions) {
if (transitions.HasPrototypeTransitions()) {
TagObject(transitions.GetPrototypeTransitions(), "(prototype transitions)",
HeapEntry::kObjectShape);
}
}
template <typename T>
void V8HeapExplorer::ExtractWeakArrayReferences(int header_size,
HeapEntry* entry, T array) {
......@@ -3015,7 +3058,8 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
JSON_S("concatenated string") ","
JSON_S("sliced string") ","
JSON_S("symbol") ","
JSON_S("bigint")) ","
JSON_S("bigint") ","
JSON_S("object shape")) ","
JSON_S("string") ","
JSON_S("number") ","
JSON_S("number") ","
......
......@@ -118,7 +118,8 @@ class HeapEntry {
kConsString = v8::HeapGraphNode::kConsString,
kSlicedString = v8::HeapGraphNode::kSlicedString,
kSymbol = v8::HeapGraphNode::kSymbol,
kBigInt = v8::HeapGraphNode::kBigInt
kBigInt = v8::HeapGraphNode::kBigInt,
kObjectShape = v8::HeapGraphNode::kObjectShape,
};
HeapEntry(HeapSnapshot* snapshot, int index, Type type, const char* name,
......@@ -431,6 +432,7 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator {
void ExtractFeedbackCellReferences(HeapEntry* entry,
FeedbackCell feedback_cell);
void ExtractPropertyCellReferences(HeapEntry* entry, PropertyCell cell);
void ExtractPrototypeInfoReferences(HeapEntry* entry, PrototypeInfo info);
void ExtractAllocationSiteReferences(HeapEntry* entry, AllocationSite site);
void ExtractArrayBoilerplateDescriptionReferences(
HeapEntry* entry, ArrayBoilerplateDescription value);
......@@ -448,6 +450,9 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator {
FeedbackVector feedback_vector);
void ExtractDescriptorArrayReferences(HeapEntry* entry,
DescriptorArray array);
void ExtractEnumCacheReferences(HeapEntry* entry, EnumCache cache);
void ExtractTransitionArrayReferences(HeapEntry* entry,
TransitionArray transitions);
template <typename T>
void ExtractWeakArrayReferences(int header_size, HeapEntry* entry, T array);
void ExtractPropertyReferences(JSObject js_obj, HeapEntry* entry);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment